diff options
author | Scott Graham <scottmg@chromium.org> | 2014-11-12 17:16:25 (GMT) |
---|---|---|
committer | Scott Graham <scottmg@chromium.org> | 2014-11-12 17:16:25 (GMT) |
commit | cc8b72a87d72a030dc5b2bb212958c0e46213a6b (patch) | |
tree | c0cbdf6e814038385bad3945b2229e7dd611eb00 /src | |
parent | 0c2982d13ea290a451efa8e8ddbaa9af1e7229a1 (diff) | |
download | Ninja-cc8b72a87d72a030dc5b2bb212958c0e46213a6b.zip Ninja-cc8b72a87d72a030dc5b2bb212958c0e46213a6b.tar.gz Ninja-cc8b72a87d72a030dc5b2bb212958c0e46213a6b.tar.bz2 |
properly guard against slash_bits overflow
Diffstat (limited to 'src')
-rw-r--r-- | src/util.cc | 7 | ||||
-rw-r--r-- | 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) { |