Browse Source

Treat paths with embedded NUL bytes as invalid (#1765)

Fixes #1763.
Wander Nauta 1 year ago
parent
commit
4ef9ed80cd
2 changed files with 16 additions and 0 deletions
  1. 1 0
      httplib.h
  2. 15 0
      test/test.cc

+ 1 - 0
httplib.h

@@ -2413,6 +2413,7 @@ inline bool is_valid_path(const std::string &path) {
     // Read component
     // Read component
     auto beg = i;
     auto beg = i;
     while (i < path.size() && path[i] != '/') {
     while (i < path.size() && path[i] != '/') {
+      if (path[i] == '\0') { return false; }
       i++;
       i++;
     }
     }
 
 

+ 15 - 0
test/test.cc

@@ -71,6 +71,15 @@ TEST(DecodeURLTest, PercentCharacter) {
       R"(descrip=Gastos áéíóúñÑ 6)");
       R"(descrip=Gastos áéíóúñÑ 6)");
 }
 }
 
 
+TEST(DecodeURLTest, PercentCharacterNUL) {
+  string expected;
+  expected.push_back('x');
+  expected.push_back('\0');
+  expected.push_back('x');
+
+  EXPECT_EQ(detail::decode_url("x%00x", false), expected);
+}
+
 TEST(EncodeQueryParamTest, ParseUnescapedChararactersTest) {
 TEST(EncodeQueryParamTest, ParseUnescapedChararactersTest) {
   string unescapedCharacters = "-_.!~*'()";
   string unescapedCharacters = "-_.!~*'()";
 
 
@@ -2482,6 +2491,12 @@ TEST_F(ServerTest, GetMethodInvalidMountPath) {
   EXPECT_EQ(StatusCode::NotFound_404, res->status);
   EXPECT_EQ(StatusCode::NotFound_404, res->status);
 }
 }
 
 
+TEST_F(ServerTest, GetMethodEmbeddedNUL) {
+  auto res = cli_.Get("/mount/dir/test.html%00.js");
+  ASSERT_TRUE(res);
+  EXPECT_EQ(StatusCode::NotFound_404, res->status);
+}
+
 TEST_F(ServerTest, GetMethodOutOfBaseDirMount) {
 TEST_F(ServerTest, GetMethodOutOfBaseDirMount) {
   auto res = cli_.Get("/mount/../www2/dir/test.html");
   auto res = cli_.Get("/mount/../www2/dir/test.html");
   ASSERT_TRUE(res);
   ASSERT_TRUE(res);