From cc8b72a87d72a030dc5b2bb212958c0e46213a6b Mon Sep 17 00:00:00 2001 From: Scott Graham Date: Wed, 12 Nov 2014 09:16:25 -0800 Subject: properly guard against slash_bits overflow --- src/util.cc | 7 +++++-- src/util_test.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/util.cc b/src/util.cc index e667992..4df81dd 100644 --- a/src/util.cc +++ b/src/util.cc @@ -130,9 +130,9 @@ bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, const char* end = start + *len; #ifdef _WIN32 - // kMaxPathComponents protects this from overflowing. unsigned int bits = 0; unsigned int bits_mask = 1; + int bits_offset = 0; // Convert \ to /, setting a bit in |bits| for each \ encountered. for (char* c = path; c < end; ++c) { switch (*c) { @@ -142,9 +142,12 @@ bool CanonicalizePath(char* path, size_t* len, unsigned int* slash_bits, // Intentional fallthrough. case '/': bits_mask <<= 1; + bits_offset++; } } - int bits_offset = 0; + if (bits_offset > 32) + return false; + bits_offset = 0; #endif if (*src == '/') { diff --git a/src/util_test.cc b/src/util_test.cc index 0073994..5bbf397 100644 --- a/src/util_test.cc +++ b/src/util_test.cc @@ -254,6 +254,34 @@ TEST(CanonicalizePath, CanonicalizeNotExceedingLen) { EXPECT_EQ(0, strncmp("foo/bar/baz.h", buf, size)); EXPECT_EQ(2, slash_bits); // Not including the trailing one. } + +TEST(CanonicalizePath, TooManyComponents) { + string path; + string err; + unsigned int slash_bits; + + // 32 is OK. + path = "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./x.h"; + EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + + // Backslashes version. + path = + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\." + "\\a\\.\\a\\.\\a\\.\\a\\.\\x.h"; + EXPECT_TRUE(CanonicalizePath(&path, &slash_bits, &err)); + EXPECT_EQ(slash_bits, 0xffff); + + // 33 is not. + path = + "a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/./a/x.h"; + EXPECT_FALSE(CanonicalizePath(&path, &slash_bits, &err)); + + // Backslashes version. + path = + "a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\.\\a\\." + "\\a\\.\\a\\.\\a\\.\\a\\.\\a\\x.h"; + EXPECT_FALSE(CanonicalizePath(&path, &slash_bits, &err)); +} #endif TEST(CanonicalizePath, EmptyResult) { -- cgit v0.12