------------------------------------------------------------ revno: 14057 revision-id: squid3@treenet.co.nz-20160524200503-1nn3hijw86ti726r parent: squid3@treenet.co.nz-20160521172919-du6cbdirqcxdjbtr fixes bug: http://bugs.squid-cache.org/show_bug.cgi?id=4485 author: Eduard Bagdasaryan committer: Amos Jeffries branch nick: 3.5 timestamp: Wed 2016-05-25 08:05:03 +1200 message: Bug 4485: off-by-one out-of-bounds Parser::Tokenizer::int64() read errors ------------------------------------------------------------ # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: squid3@treenet.co.nz-20160524200503-1nn3hijw86ti726r # target_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # testament_sha1: a7a643f09c2d39665e013fc7a6bc87577f0890e0 # timestamp: 2016-05-24 20:51:02 +0000 # source_branch: http://bzr.squid-cache.org/bzr/squid3/3.5 # base_revision_id: squid3@treenet.co.nz-20160521172919-\ # du6cbdirqcxdjbtr # # Begin patch === modified file 'src/parser/Tokenizer.cc' --- src/parser/Tokenizer.cc 2016-01-01 00:14:27 +0000 +++ src/parser/Tokenizer.cc 2016-05-24 20:05:03 +0000 @@ -111,8 +111,9 @@ } else if (*s == '+') { ++s; } + if (s >= end) return false; - if (( base == 0 || base == 16) && *s == '0' && (s+1 <= end ) && + if (( base == 0 || base == 16) && *s == '0' && (s+1 < end ) && tolower(*(s+1)) == 'x') { s += 2; base = 16; @@ -135,7 +136,8 @@ int any = 0, c; int64_t acc = 0; - for (c = *s++; s <= end; c = *s++) { + do { + c = *s; if (xisdigit(c)) { c -= '0'; } else if (xisalpha(c)) { @@ -152,7 +154,7 @@ acc *= base; acc += c; } - } + } while (++s < end); if (any == 0) // nothing was parsed return false; @@ -164,6 +166,6 @@ acc = -acc; result = acc; - return success(s - buf_.rawContent() - 1); + return success(s - buf_.rawContent()); } === modified file 'src/tests/testTokenizer.cc' --- src/tests/testTokenizer.cc 2016-01-01 00:14:27 +0000 +++ src/tests/testTokenizer.cc 2016-05-24 20:05:03 +0000 @@ -144,6 +144,7 @@ const int64_t benchmark = 1234; CPPUNIT_ASSERT(t.int64(rv, 10)); CPPUNIT_ASSERT_EQUAL(benchmark,rv); + CPPUNIT_ASSERT(t.buf().isEmpty()); } // successful parse, autodetect base @@ -153,6 +154,7 @@ const int64_t benchmark = 1234; CPPUNIT_ASSERT(t.int64(rv)); CPPUNIT_ASSERT_EQUAL(benchmark,rv); + CPPUNIT_ASSERT(t.buf().isEmpty()); } // successful parse, autodetect base @@ -162,6 +164,7 @@ const int64_t benchmark = 01234; CPPUNIT_ASSERT(t.int64(rv)); CPPUNIT_ASSERT_EQUAL(benchmark,rv); + CPPUNIT_ASSERT(t.buf().isEmpty()); } // successful parse, autodetect base @@ -171,6 +174,7 @@ const int64_t benchmark = 0x12f4; CPPUNIT_ASSERT(t.int64(rv)); CPPUNIT_ASSERT_EQUAL(benchmark,rv); + CPPUNIT_ASSERT(t.buf().isEmpty()); } // API mismatch: don't eat leading space @@ -178,6 +182,7 @@ int64_t rv; Parser::Tokenizer t(SBuf(" 1234")); CPPUNIT_ASSERT(!t.int64(rv)); + CPPUNIT_ASSERT_EQUAL(SBuf(" 1234"), t.buf()); } // API mismatch: don't eat multiple leading spaces @@ -185,6 +190,7 @@ int64_t rv; Parser::Tokenizer t(SBuf(" 1234")); CPPUNIT_ASSERT(!t.int64(rv)); + CPPUNIT_ASSERT_EQUAL(SBuf(" 1234"), t.buf()); } // trailing spaces @@ -222,6 +228,7 @@ int64_t rv; Parser::Tokenizer t(SBuf("1029397752385698678762234")); CPPUNIT_ASSERT(!t.int64(rv)); + CPPUNIT_ASSERT_EQUAL(SBuf("1029397752385698678762234"), t.buf()); } // buffered sub-string parsing @@ -233,6 +240,7 @@ CPPUNIT_ASSERT_EQUAL(SBuf("22"),t.buf()); CPPUNIT_ASSERT(t.int64(rv)); CPPUNIT_ASSERT_EQUAL(benchmark,rv); + CPPUNIT_ASSERT(t.buf().isEmpty()); } // base-16, prefix