From 0fe0928b51782ceea91f537c8f0d05d80471c174 Mon Sep 17 00:00:00 2001 From: Dustin Sallings Date: Wed, 18 Mar 2009 18:54:01 -0700 Subject: Use safe strto.*l functions for parsing info in text sets. Thanks to Toru for pointing this out. --- memcached.c | 27 ++++++++++++++++----------- t/cas.t | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/memcached.c b/memcached.c index 205c8cb..1772b8c 100644 --- a/memcached.c +++ b/memcached.c @@ -2599,7 +2599,8 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens, static void process_update_command(conn *c, token_t *tokens, const size_t ntokens, int comm, bool handle_cas) { char *key; size_t nkey; - int flags; + unsigned int flags; + int32_t exptime_int = 0; time_t exptime; int vlen; uint64_t req_cas_id=0; @@ -2617,19 +2618,23 @@ static void process_update_command(conn *c, token_t *tokens, const size_t ntoken key = tokens[KEY_TOKEN].value; nkey = tokens[KEY_TOKEN].length; - flags = strtoul(tokens[2].value, NULL, 10); - exptime = strtol(tokens[3].value, NULL, 10); - vlen = strtol(tokens[4].value, NULL, 10); + if (! (safe_strtoul(tokens[2].value, (uint32_t *)&flags) + && safe_strtol(tokens[3].value, &exptime_int) + && safe_strtol(tokens[4].value, (int32_t *)&vlen))) { + out_string(c, "CLIENT_ERROR bad command line format"); + return; + } + + /* Ubuntu 8.04 breaks when I pass exptime to safe_strtol */ + exptime = exptime_int; // does cas value exist? if (handle_cas) { - req_cas_id = strtoull(tokens[5].value, NULL, 10); - } - - if (errno == ERANGE || ((flags == 0 || exptime == 0) && errno == EINVAL) - || vlen < 0) { - out_string(c, "CLIENT_ERROR bad command line format"); - return; + if (!safe_strtoull(tokens[5].value, &req_cas_id) + || vlen < 0 ) { + out_string(c, "CLIENT_ERROR bad command line format"); + return; + } } if (settings.detail_enabled) { diff --git a/t/cas.t b/t/cas.t index a84fdd9..f2c2f50 100644 --- a/t/cas.t +++ b/t/cas.t @@ -1,7 +1,7 @@ #!/usr/bin/perl use strict; -use Test::More tests => 39; +use Test::More tests => 43; use FindBin qw($Bin); use lib "$Bin/lib"; use MemcachedTest; @@ -16,6 +16,22 @@ my @result2; ok($sock != $sock2, "have two different connections open"); +sub check_args { + my ($line, $name) = @_; + + my $svr = new_memcached(); + my $s = $svr->sock; + + print $s $line; + is(scalar <$s>, "CLIENT_ERROR bad command line format\r\n", $name); + undef $svr; +} + +check_args "cas bad blah 0 0 0\r\n\r\n", "bad flags"; +check_args "cas bad 0 blah 0 0\r\n\r\n", "bad exp"; +check_args "cas bad 0 0 blah 0\r\n\r\n", "bad cas"; +check_args "cas bad 0 0 0 blah\r\n\r\n", "bad size"; + # gets foo (should not exist) print $sock "gets foo\r\n"; is(scalar <$sock>, "END\r\n", "gets failed"); -- cgit v1.2.1