diff --git a/memcached.c b/memcached.c index 59b42849fe..c074aa602e 100644 --- a/memcached.c +++ b/memcached.c @@ -2493,27 +2493,32 @@ static void process_update_command(conn *c, token_t *tokens, const size_t ntoken // does cas value exist? if (handle_cas) { - if (!safe_strtoull(tokens[5].value, &req_cas_id) - || vlen < 0 ) { + if (!safe_strtoull(tokens[5].value, &req_cas_id)) { out_string(c, "CLIENT_ERROR bad command line format"); return; } } + vlen += 2; + if (vlen < 0 || vlen - 2 < 0) { + out_string(c, "CLIENT_ERROR bad command line format"); + return; + } + if (settings.detail_enabled) { stats_prefix_record_set(key, nkey); } - it = item_alloc(key, nkey, flags, realtime(exptime), vlen+2); + it = item_alloc(key, nkey, flags, realtime(exptime), vlen); if (it == 0) { - if (! item_size_ok(nkey, flags, vlen + 2)) + if (! item_size_ok(nkey, flags, vlen)) out_string(c, "SERVER_ERROR object too large for cache"); else out_string(c, "SERVER_ERROR out of memory storing object"); /* swallow the data line */ c->write_and_go = conn_swallow; - c->sbytes = vlen + 2; + c->sbytes = vlen; /* Avoid stale data persisting in cache because we failed alloc. * Unacceptable for SET. Anywhere else too? */ diff --git a/t/issue_70.t b/t/issue_70.t new file mode 100644 index 0000000000..95e39db11c --- /dev/null +++ b/t/issue_70.t @@ -0,0 +1,22 @@ +#!/usr/bin/perl + +use strict; +use Test::More tests => 4; +use FindBin qw($Bin); +use lib "$Bin/lib"; +use MemcachedTest; + +my $server = new_memcached(); +my $sock = $server->sock; + +print $sock "set issue70 0 0 0\r\n\r\n"; +is (scalar <$sock>, "STORED\r\n", "stored issue70"); + +print $sock "set issue70 0 0 -1\r\n"; +is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n"); + +print $sock "set issue70 0 0 4294967295\r\n"; +is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n"); + +print $sock "set issue70 0 0 2147483647\r\nscoobyscoobydoo"; +is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n");