summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-05-15 18:40:50 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-05-15 18:40:50 +0900
commitbafbbe7c1d5ea39e67e233f9c32975fda7843874 (patch)
treef89e784f062e108935662c52f66eb559f6de61db
parent6976ffed9e96ccc70f161aa5a38abddaf9d9befe (diff)
Allow subsecond value in ns cookie.txt file's expiry time field
-rw-r--r--src/NsCookieParser.cc11
-rw-r--r--src/util.cc27
-rw-r--r--src/util.h4
-rw-r--r--test/CookieStorageTest.cc4
-rw-r--r--test/NsCookieParserTest.cc4
-rw-r--r--test/UtilTest2.cc19
-rw-r--r--test/nscookietest.txt4
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<Cookie> 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<int64_t>(expiryTimeDouble);
}
if (std::numeric_limits<time_t>::max() < expiryTime) {
expiryTime = std::numeric_limits<time_t>::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<int> parseIntSegments(const std::string& src)
{
SegList<int> 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<int> 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