From bafbbe7c1d5ea39e67e233f9c32975fda7843874 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 15 May 2016 18:40:50 +0900 Subject: [PATCH] Allow subsecond value in ns cookie.txt file's expiry time field --- src/NsCookieParser.cc | 11 ++++++++--- src/util.cc | 27 +++++++++++++++++++++++++++ src/util.h | 4 ++++ test/CookieStorageTest.cc | 4 ++-- test/NsCookieParserTest.cc | 4 ++-- test/UtilTest2.cc | 19 +++++++++++++++++++ test/nscookietest.txt | 4 ++-- 7 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/NsCookieParser.cc b/src/NsCookieParser.cc index e484df8e..77ca25ab 100644 --- a/src/NsCookieParser.cc +++ b/src/NsCookieParser.cc @@ -69,9 +69,14 @@ std::unique_ptr parseNsCookie(const std::string& cookieStr, return nullptr; } int64_t expiryTime; - if (!util::parseLLIntNoThrow(expiryTime, - std::string(vs[4].first, vs[4].second))) { - return nullptr; + { + // chrome extension uses subsecond resolution for expiry time. + double expiryTimeDouble; + if (!util::parseDoubleNoThrow(expiryTimeDouble, + std::string(vs[4].first, vs[4].second))) { + return nullptr; + } + expiryTime = static_cast(expiryTimeDouble); } if (std::numeric_limits::max() < expiryTime) { expiryTime = std::numeric_limits::max(); diff --git a/src/util.cc b/src/util.cc index a2590235..3c9c19b1 100644 --- a/src/util.cc +++ b/src/util.cc @@ -596,6 +596,33 @@ bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base) } } +bool parseDoubleNoThrow(double& res, const std::string& s) +{ + if (s.empty()) { + return false; + } + + errno = 0; + char* endptr; + auto d = strtod(s.c_str(), &endptr); + + if (errno == ERANGE) { + return false; + } + + if (endptr != s.c_str() + s.size()) { + for (auto i = std::begin(s) + (endptr - s.c_str()); i != std::end(s); ++i) { + if (!isspace(*i)) { + return false; + } + } + } + + res = d; + + return true; +} + SegList parseIntSegments(const std::string& src) { SegList sgl; diff --git a/src/util.h b/src/util.h index 25183b5c..76ecb549 100644 --- a/src/util.h +++ b/src/util.h @@ -280,6 +280,10 @@ bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base = 10); bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10); +// Parses |s| as floating point number, and stores the result into +// |res|. This function returns true if it succeeds. +bool parseDoubleNoThrow(double& res, const std::string& s); + SegList parseIntSegments(const std::string& src); // Parses string which specifies the range of piece index for higher diff --git a/test/CookieStorageTest.cc b/test/CookieStorageTest.cc index b9e741b6..a9966a64 100644 --- a/test/CookieStorageTest.cc +++ b/test/CookieStorageTest.cc @@ -328,10 +328,10 @@ void CookieStorageTest::testLoad() c = cookies[3]; CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName()); CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue()); - CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime()); + CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime()); CPPUNIT_ASSERT(c->getPersistent()); CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath()); - CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain()); CPPUNIT_ASSERT(!c->getSecure()); } diff --git a/test/NsCookieParserTest.cc b/test/NsCookieParserTest.cc index 45d81004..23fb4016 100644 --- a/test/NsCookieParserTest.cc +++ b/test/NsCookieParserTest.cc @@ -69,9 +69,9 @@ void NsCookieParserTest::testParse() c = cookies[3].get(); CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName()); CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue()); - CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime()); + CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime()); CPPUNIT_ASSERT(c->getPersistent()); - CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain()); + CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain()); CPPUNIT_ASSERT(c->getHostOnly()); CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath()); CPPUNIT_ASSERT(!c->getSecure()); diff --git a/test/UtilTest2.cc b/test/UtilTest2.cc index 03a28411..544df0d5 100644 --- a/test/UtilTest2.cc +++ b/test/UtilTest2.cc @@ -66,6 +66,7 @@ class UtilTest2 : public CppUnit::TestFixture { CPPUNIT_TEST(testInPrivateAddress); CPPUNIT_TEST(testSecfmt); CPPUNIT_TEST(testTlsHostnameMatch); + CPPUNIT_TEST(testParseDoubleNoThrow); CPPUNIT_TEST_SUITE_END(); private: @@ -115,6 +116,7 @@ public: void testInPrivateAddress(); void testSecfmt(); void testTlsHostnameMatch(); + void testParseDoubleNoThrow(); }; CPPUNIT_TEST_SUITE_REGISTRATION(UtilTest2); @@ -978,4 +980,21 @@ void UtilTest2::testTlsHostnameMatch() CPPUNIT_ASSERT(!util::tlsHostnameMatch("xn--*.a.b", "xn--c.a.b")); } +void UtilTest2::testParseDoubleNoThrow() +{ + double n; + + CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, " 123 ")); + CPPUNIT_ASSERT_EQUAL(123., n); + + CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "3.14")); + CPPUNIT_ASSERT_EQUAL(3.14, n); + + CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "-3.14")); + CPPUNIT_ASSERT_EQUAL(-3.14, n); + + CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, "")); + CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, "123x")); +} + } // namespace aria2 diff --git a/test/nscookietest.txt b/test/nscookietest.txt index 7b7d9e84..5eed9f33 100644 --- a/test/nscookietest.txt +++ b/test/nscookietest.txt @@ -5,5 +5,5 @@ expired FALSE / FALSE 1000 user me 192.168.0.1 TRUE /cgi-bin FALSE 0 passwd secret badformat -overflow FALSE / FALSE 9223372036854775807 TAX 1000 -.example.org TRUE / FALSE 2147483647 novalue +something FALSE / FALSE 1463304912.5 TAX 1000 +.example.org TRUE / FALSE 2147483647.123 novalue