From 9763b8e9b681d1d6713b95e4d7ce6ffeafeafca5 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Sat, 23 Feb 2013 05:17:33 -0500 Subject: [PATCH] Fix for lp:1123153 (poor use of strtol). --- clients/memaslap.c | 27 +++-- clients/memcapable.cc | 17 +++ clients/memerror.cc | 3 +- clients/memflush.cc | 7 ++ clients/memping.cc | 16 ++- clients/memrm.cc | 7 ++ clients/memslap.cc | 20 +++- clients/memtouch.cc | 8 ++ clients/ms_conn.c | 5 + libmemcached/parse.cc | 16 ++- libmemcached/response.cc | 34 ++++-- libmemcached/stats.cc | 153 ++++++++++++++++++++++++--- libmemcachedprotocol/ascii_handler.c | 38 +++++++ libtest/main.cc | 16 ++- 14 files changed, 326 insertions(+), 41 deletions(-) diff --git a/clients/memaslap.c b/clients/memaslap.c index 1b5c223a..02907945 100644 --- a/clients/memaslap.c +++ b/clients/memaslap.c @@ -378,7 +378,13 @@ static int64_t ms_parse_size() char unit= optarg[strlen(optarg) - 1]; optarg[strlen(optarg) - 1]= '\0'; + errno= 0; ret= strtoll(optarg, (char **)NULL, 10); + if (errno != 0) + { + fprintf(stderr, "strtoll(optarg,..): %s\n", strerror(errno)); + exit(1); + } switch (unit) { @@ -434,8 +440,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_CONCURRENCY: /* --concurrency or -c */ + errno= 0; ms_setting.nconns= (uint32_t)strtoul(optarg, (char **) NULL, 10); - if (ms_setting.nconns <= 0) + if (ms_setting.nconns <= 0 || errno != 0) { fprintf(stderr, "Concurrency must be greater than 0.:-)\n"); exit(1); @@ -443,8 +450,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_EXECUTE_NUMBER: /* --execute_number or -x */ + errno= 0; ms_setting.exec_num= (int)strtol(optarg, (char **) NULL, 10); - if (ms_setting.exec_num <= 0) + if (ms_setting.exec_num <= 0 || errno != 0) { fprintf(stderr, "Execute number must be greater than 0.:-)\n"); exit(1); @@ -452,8 +460,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_THREAD_NUMBER: /* --threads or -T */ + errno= 0; ms_setting.nthreads= (uint32_t)strtoul(optarg, (char **) NULL, 10); - if (ms_setting.nthreads <= 0) + if (ms_setting.nthreads <= 0 || errno != 0) { fprintf(stderr, "Threads number must be greater than 0.:-)\n"); exit(1); @@ -461,8 +470,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_FIXED_LTH: /* --fixed_size or -X */ + errno= 0; ms_setting.fixed_value_size= (size_t)strtoull(optarg, (char **) NULL, 10); - if ((ms_setting.fixed_value_size <= 0) + if ((ms_setting.fixed_value_size <= 0 || errno != 0) || (ms_setting.fixed_value_size > MAX_VALUE_SIZE)) { fprintf(stderr, "Value size must be between 0 and 1M.:-)\n"); @@ -482,8 +492,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_GETS_DIVISION: /* --division or -d */ + errno= 0; ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10); - if (ms_setting.mult_key_num <= 0) + if (ms_setting.mult_key_num <= 0 || errno != 0) { fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n"); exit(1); @@ -568,8 +579,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_SOCK_PER_CONN: /* --conn_sock or -n */ + errno= 0; ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10); - if (ms_setting.sock_per_conn <= 0) + if (ms_setting.sock_per_conn <= 0 || errno != 0) { fprintf(stderr, "Number of socks of each concurrency " "must be greater than 0.:-)\n"); @@ -605,8 +617,9 @@ static void ms_options_parse(int argc, char *argv[]) break; case OPT_REP_WRITE_SRV: /* --rep_write or -p */ + errno= 0; ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10); - if (ms_setting.rep_write_srv <= 0) + if (ms_setting.rep_write_srv <= 0 || errno != 0) { fprintf(stderr, "Number of replication writing server must be greater " diff --git a/clients/memcapable.cc b/clients/memcapable.cc index 0343e15d..b38cf311 100644 --- a/clients/memcapable.cc +++ b/clients/memcapable.cc @@ -1389,11 +1389,15 @@ static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_ verify(*key != NULL); char *ptr= end + 1; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + errno= 0; *ndata = (ssize_t)strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(end != NULL); while (end and *end != '\n' and isspace(*end)) @@ -1424,11 +1428,16 @@ static enum test_return ascii_get_value(const char *key, const char *value) char *ptr= buffer + 6 + strlen(key) + 1; char *end; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + + errno= 0; val= strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); @@ -1486,15 +1495,23 @@ static enum test_return ascii_gets_value(const char *key, const char *value, char *ptr= buffer + 6 + strlen(key) + 1; char *end; + errno= 0; unsigned long val= strtoul(ptr, &end, 10); /* flags */ + verify(errno == 0); verify(ptr != end); verify(val == 0); verify(end != NULL); + + errno= 0; val= strtoul(end, &end, 10); /* size */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); + + errno= 0; *cas= strtoul(end, &end, 10); /* cas */ + verify(errno == 0); verify(ptr != end); verify(val == datasize); verify(end != NULL); diff --git a/clients/memerror.cc b/clients/memerror.cc index bc9a6a75..3cee64cc 100644 --- a/clients/memerror.cc +++ b/clients/memerror.cc @@ -47,7 +47,8 @@ int main(int argc, char *argv[]) char *nptr; unsigned long value= strtoul(argv[optind], &nptr, 10); - if ((nptr == argv[optind] and value == 0) or + if ((errno != 0) or + (nptr == argv[optind] and value == 0) or (value == ULONG_MAX and errno == ERANGE) or (value == 0 and errno == EINVAL)) { diff --git a/clients/memflush.cc b/clients/memflush.cc index 67df7c7a..17abff70 100644 --- a/clients/memflush.cc +++ b/clients/memflush.cc @@ -11,6 +11,7 @@ */ #include "mem_config.h" +#include #include #include #include @@ -147,7 +148,13 @@ void options_parse(int argc, char *argv[]) break; case OPT_EXPIRE: /* --expire */ + errno= 0; opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10); + if (errno != 0) + { + std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::cerr; + exit(EXIT_FAILURE); + } break; case OPT_USERNAME: diff --git a/clients/memping.cc b/clients/memping.cc index 39b4fbe6..39546d4f 100644 --- a/clients/memping.cc +++ b/clients/memping.cc @@ -11,10 +11,12 @@ */ #include "mem_config.h" -#include -#include -#include +#include +#include +#include #include +#include + #include #include #include "client_options.h" @@ -139,7 +141,13 @@ void options_parse(int argc, char *argv[]) break; case OPT_EXPIRE: /* --expire */ - opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10); + errno= 0; + opt_expire= time_t(strtoll(optarg, (char **)NULL, 10)); + if (errno != 0) + { + std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::cerr; + exit(EXIT_FAILURE); + } break; case OPT_USERNAME: diff --git a/clients/memrm.cc b/clients/memrm.cc index a559ef90..4e4cd479 100644 --- a/clients/memrm.cc +++ b/clients/memrm.cc @@ -11,6 +11,7 @@ */ #include "mem_config.h" +#include #include #include #include @@ -204,7 +205,13 @@ static void options_parse(int argc, char *argv[]) break; case OPT_EXPIRE: /* --expire */ + errno= 0; opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10); + if (errno != 0) + { + std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::cerr; + exit(EXIT_FAILURE); + } break; case OPT_HASH: diff --git a/clients/memslap.cc b/clients/memslap.cc index d32b1c04..e66ab0fd 100644 --- a/clients/memslap.cc +++ b/clients/memslap.cc @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,6 @@ #include #include #include -#include #include #include @@ -468,15 +468,33 @@ void options_parse(int argc, char *argv[]) break; case OPT_SLAP_CONCURRENCY: + errno= 0; opt_concurrency= (unsigned int)strtoul(optarg, (char **)NULL, 10); + if (errno != 0) + { + fprintf(stderr, "Invalid value for concurrency: %s\n", optarg); + exit(EXIT_FAILURE); + } break; case OPT_SLAP_EXECUTE_NUMBER: + errno= 0; opt_execute_number= (unsigned int)strtoul(optarg, (char **)NULL, 10); + if (errno != 0) + { + fprintf(stderr, "Invalid value for execute: %s\n", optarg); + exit(EXIT_FAILURE); + } break; case OPT_SLAP_INITIAL_LOAD: + errno= 0; opt_createial_load= (unsigned int)strtoul(optarg, (char **)NULL, 10); + if (errno != 0) + { + fprintf(stderr, "Invalid value for initial load: %s\n", optarg); + exit(EXIT_FAILURE); + } break; case OPT_QUIET: diff --git a/clients/memtouch.cc b/clients/memtouch.cc index 73429e23..19213569 100644 --- a/clients/memtouch.cc +++ b/clients/memtouch.cc @@ -12,11 +12,13 @@ #include +#include #include #include #include #include #include + #include #include "utilities.h" @@ -212,7 +214,13 @@ void options_parse(int argc, char *argv[]) break; case OPT_EXPIRE: + errno= 0; expiration= time_t(strtoul(optarg, (char **)NULL, 10)); + if (errno != 0) + { + fprintf(stderr, "Invalid value for --expire: %s\n", optarg); + exit(EXIT_FAILURE); + } break; case OPT_QUIET: diff --git a/clients/ms_conn.c b/clients/ms_conn.c index 2cbc7e0b..2afc9fa1 100644 --- a/clients/ms_conn.c +++ b/clients/ms_conn.c @@ -1160,7 +1160,12 @@ static int ms_ascii_process_line(ms_conn_t *c, char *command) { token_t tokens[MAX_TOKENS]; ms_tokenize_command(command, tokens, MAX_TOKENS); + errno= 0; value_len= strtol(tokens[VALUELEN_TOKEN].value, NULL, 10); + if (errno != 0) + { + printf("<%d ERROR %s\n", c->sfd, strerror(errno)); + } c->currcmd.key_prefix= *(uint64_t *)tokens[KEY_TOKEN].value; /* diff --git a/libmemcached/parse.cc b/libmemcached/parse.cc index 3284a4f6..7665b731 100644 --- a/libmemcached/parse.cc +++ b/libmemcached/parse.cc @@ -87,7 +87,13 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) ptr++; + errno= 0; port= (in_port_t) strtoul(ptr, (char **)NULL, 10); + if (errno != 0) + { + memcached_server_free(servers); + return NULL; + } ptr2= index(ptr, ' '); if (! ptr2) @@ -96,14 +102,22 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings) if (ptr2) { ptr2++; - weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10); + errno= 0; + weight= uint32_t(strtoul(ptr2, (char **)NULL, 10)); + if (errno != 0) + { + memcached_server_free(servers); + return NULL; + } } } servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc); if (isspace(*begin_ptr)) + { begin_ptr++; + } } return servers; diff --git a/libmemcached/response.cc b/libmemcached/response.cc index 391c9309..7503c5a0 100644 --- a/libmemcached/response.cc +++ b/libmemcached/response.cc @@ -90,9 +90,10 @@ static memcached_return_t textual_value_fetch(org::libmemcached::Instance* insta } for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {}; + errno= 0; result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10); - if (end_ptr == string_ptr) + if (errno != 0 or end_ptr == string_ptr) { goto read_error; } @@ -105,9 +106,10 @@ static memcached_return_t textual_value_fetch(org::libmemcached::Instance* insta } for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {}; + errno= 0; value_length= (size_t)strtoull(next_ptr, &string_ptr, 10); - if (end_ptr == string_ptr) + if (errno != 0 or end_ptr == string_ptr) { goto read_error; } @@ -122,10 +124,11 @@ static memcached_return_t textual_value_fetch(org::libmemcached::Instance* insta { string_ptr++; for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {}; + errno= 0; result->item_cas= strtoull(next_ptr, &string_ptr, 10); } - if (end_ptr < string_ptr) + if (errno != 0 or end_ptr < string_ptr) { goto read_error; } @@ -238,8 +241,9 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* char *response_ptr= index(buffer, ' '); char *endptr; + errno= 0; long int version= strtol(response_ptr, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version")); @@ -247,8 +251,9 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* instance->major_version= uint8_t(version); endptr++; + errno= 0; version= strtol(endptr, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version")); @@ -256,8 +261,9 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* instance->minor_version= uint8_t(version); endptr++; + errno= 0; version= strtol(endptr, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version")); @@ -442,6 +448,7 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* case '8': /* INCR/DECR response */ case '9': /* INCR/DECR response */ { + errno= 0; unsigned long long int auto_return_value= strtoull(buffer, (char **)NULL, 10); if (auto_return_value == ULLONG_MAX and errno == ERANGE) @@ -456,6 +463,12 @@ static memcached_return_t textual_read_one_response(org::libmemcached::Instance* return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("Numeric response was out of range")); } + else if (errno != 0) + { + result->numeric_value= UINT64_MAX; + return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, + memcached_literal_param("Numeric response was out of range")); + } result->numeric_value= uint64_t(auto_return_value); @@ -620,8 +633,9 @@ static memcached_return_t binary_read_one_response(org::libmemcached::Instance* } char *endptr; + errno= 0; long int version= strtol(version_buffer, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX or version == 0) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version")); @@ -629,8 +643,9 @@ static memcached_return_t binary_read_one_response(org::libmemcached::Instance* instance->major_version= uint8_t(version); endptr++; + errno= 0; version= strtol(endptr, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version")); @@ -638,8 +653,9 @@ static memcached_return_t binary_read_one_response(org::libmemcached::Instance* instance->minor_version= uint8_t(version); endptr++; + errno= 0; version= strtol(endptr, &endptr, 10); - if (version == LONG_MIN or version == LONG_MAX or errno == EINVAL or version > UINT8_MAX) + if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX) { instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX; return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version")); diff --git a/libmemcached/stats.cc b/libmemcached/stats.cc index 89d5be52..01a8baf6 100644 --- a/libmemcached/stats.cc +++ b/libmemcached/stats.cc @@ -2,7 +2,7 @@ * * Libmemcached library * - * Copyright (C) 2011 Data Differential, http://datadifferential.com/ + * Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -91,7 +91,12 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key } else if (strcmp("pid", key) == 0) { + errno= 0; int64_t temp= strtoll(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } if (temp <= INT32_MAX and ( sizeof(pid_t) == sizeof(int32_t) )) { @@ -109,11 +114,21 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key } else if (not strcmp("uptime", key)) { + errno= 0; memc_stat->uptime= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("time", key)) { + errno= 0; memc_stat->time= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("version", key)) { @@ -122,7 +137,12 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key } else if (not strcmp("pointer_size", key)) { + errno= 0; memc_stat->pointer_size= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("rusage_user", key)) { @@ -130,8 +150,20 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {}; *walk_ptr= 0; walk_ptr++; + + errno= 0; memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } + + errno= 0; memc_stat->rusage_user_microseconds= strtoul(walk_ptr, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("rusage_system", key)) { @@ -139,85 +171,172 @@ static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {}; *walk_ptr= 0; walk_ptr++; + + errno= 0; memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } + + errno= 0; memc_stat->rusage_system_microseconds= strtoul(walk_ptr, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("curr_items", key)) { + errno= 0; memc_stat->curr_items= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("total_items", key)) { + errno= 0; memc_stat->total_items= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("bytes_read", key)) { + errno= 0; memc_stat->bytes_read= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("bytes_written", key)) { + errno= 0; memc_stat->bytes_written= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("bytes", key)) { + errno= 0; memc_stat->bytes= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("curr_connections", key)) { + errno= 0; memc_stat->curr_connections= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("total_connections", key)) { + errno= 0; memc_stat->total_connections= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("connection_structures", key)) { + errno= 0; memc_stat->connection_structures= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("cmd_get", key)) { + errno= 0; memc_stat->cmd_get= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("cmd_set", key)) { + errno= 0; memc_stat->cmd_set= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("get_hits", key)) { + errno= 0; memc_stat->get_hits= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("get_misses", key)) { + errno= 0; memc_stat->get_misses= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("evictions", key)) { + errno= 0; memc_stat->evictions= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("limit_maxbytes", key)) { + errno= 0; memc_stat->limit_maxbytes= strtoull(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } else if (not strcmp("threads", key)) { + errno= 0; memc_stat->threads= strtoul(value, (char **)NULL, 10); + if (errno != 0) + { + return MEMCACHED_FAILURE; + } } - else if (not (strcmp("delete_misses", key) == 0 or /* New stats in the 1.3 beta */ - strcmp("delete_hits", key) == 0 or /* Just swallow them for now.. */ - strcmp("incr_misses", key) == 0 or - strcmp("incr_hits", key) == 0 or - strcmp("decr_misses", key) == 0 or - strcmp("decr_hits", key) == 0 or - strcmp("cas_misses", key) == 0 or - strcmp("cas_hits", key) == 0 or - strcmp("cas_badval", key) == 0 or - strcmp("cmd_flush", key) == 0 or - strcmp("accepting_conns", key) == 0 or - strcmp("listen_disabled_num", key) == 0 or - strcmp("conn_yields", key) == 0 or - strcmp("auth_cmds", key) == 0 or - strcmp("auth_errors", key) == 0 or - strcmp("reclaimed", key) == 0)) + else if ((strcmp("delete_misses", key) == 0 or /* New stats in the 1.3 beta */ + strcmp("delete_hits", key) == 0 or /* Just swallow them for now.. */ + strcmp("incr_misses", key) == 0 or + strcmp("incr_hits", key) == 0 or + strcmp("decr_misses", key) == 0 or + strcmp("decr_hits", key) == 0 or + strcmp("cas_misses", key) == 0 or + strcmp("cas_hits", key) == 0 or + strcmp("cas_badval", key) == 0 or + strcmp("cmd_flush", key) == 0 or + strcmp("accepting_conns", key) == 0 or + strcmp("listen_disabled_num", key) == 0 or + strcmp("conn_yields", key) == 0 or + strcmp("auth_cmds", key) == 0 or + strcmp("auth_errors", key) == 0 or + strcmp("reclaimed", key) == 0) == 0) { WATCHPOINT_STRING(key); /* return MEMCACHED_UNKNOWN_STAT_KEY; */ diff --git a/libmemcachedprotocol/ascii_handler.c b/libmemcachedprotocol/ascii_handler.c index 8cd29720..449b650d 100644 --- a/libmemcachedprotocol/ascii_handler.c +++ b/libmemcachedprotocol/ascii_handler.c @@ -561,7 +561,12 @@ static void process_arithmetic(memcached_protocol_client_st *client, uint64_t cas; uint64_t result; + errno= 0; uint64_t delta= strtoull(tokens[2], NULL, 10); + if (errno != 0) + { + return; // Error + } protocol_binary_response_status rval; if (client->ascii_command == INCR_CMD) @@ -667,7 +672,12 @@ static void process_flush(memcached_protocol_client_st *client, uint32_t timeout= 0; if (ntokens == 2) { + errno= 0; timeout= (uint32_t)strtoul(tokens[1], NULL, 10); + if (errno != 0) + { + return; // Error + } } protocol_binary_response_status rval; @@ -706,9 +716,30 @@ static inline int process_storage_command(memcached_protocol_client_st *client, return -1; } + errno= 0; uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10); + if (errno != 0) + { + /* return error */ + raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + return -1; + } + uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10); + if (errno != 0) + { + /* return error */ + raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + return -1; + } + unsigned long nbytes= strtoul(tokens[4], NULL, 10); + if (errno != 0) + { + /* return error */ + raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + return -1; + } /* Do we have all data? */ unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */ @@ -743,7 +774,14 @@ static inline int process_storage_command(memcached_protocol_client_st *client, timeout, &result_cas); break; case CAS_CMD: + errno= 0; cas= strtoull(tokens[5], NULL, 10); + if (errno != 0) + { + /* return error */ + raw_response_handler(client, "CLIENT_ERROR: bad key\r\n"); + return -1; + } /* FALLTHROUGH */ case REPLACE_CMD: rval= client->root->callback->interface.v1.replace(client, key, diff --git a/libtest/main.cc b/libtest/main.cc index fe8938b9..80ffa769 100644 --- a/libtest/main.cc +++ b/libtest/main.cc @@ -158,7 +158,14 @@ int main(int argc, char *argv[]) break; case OPT_LIBYATL_REPEAT: + errno= 0; opt_repeat= strtoul(optarg, (char **) NULL, 10); + if (errno != 0) + { + Error << "unknown value passed to --repeat: `" << optarg << "`"; + exit(EXIT_FAILURE); + } + break; case OPT_LIBYATL_MATCH_COLLECTION: @@ -186,9 +193,16 @@ int main(int argc, char *argv[]) srandom((unsigned int)time(NULL)); - if (bool(getenv("YATL_REPEAT")) and (strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10) > 1)) + errno= 0; + if (bool(getenv("YATL_REPEAT"))) { + errno= 0; opt_repeat= strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10); + if (errno != 0) + { + Error << "ENV YATL_REPEAT passed an invalid value: `" << getenv("YATL_REPEAT") << "`"; + exit(EXIT_FAILURE); + } } if ((bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "0") == 0)) or opt_quiet) -- 2.30.2