Kaynağa Gözat

use strict hex parsing in decode_query_component (#2472)

metsw24-max 3 ay önce
ebeveyn
işleme
28d95937b5
2 değiştirilmiş dosya ile 16 ekleme ve 5 silme
  1. 3 5
      httplib.h
  2. 13 0
      test/test.cc

+ 3 - 5
httplib.h

@@ -9734,11 +9734,9 @@ inline std::string decode_query_component(const std::string &component,
 
   for (size_t i = 0; i < component.size(); i++) {
     if (component[i] == '%' && i + 2 < component.size()) {
-      std::string hex = component.substr(i + 1, 2);
-      char *end;
-      unsigned long value = std::strtoul(hex.c_str(), &end, 16);
-      if (end == hex.c_str() + 2) {
-        result += static_cast<char>(value);
+      auto val = 0;
+      if (detail::from_hex_to_i(component, i + 1, 2, val)) {
+        result += static_cast<char>(val);
         i += 2;
       } else {
         result += component[i];

+ 13 - 0
test/test.cc

@@ -386,6 +386,19 @@ TEST(DecodePathTest, UnicodeEncoding) {
   EXPECT_EQ("", decode_path_component("%uD800"));
 }
 
+TEST(DecodeQueryTest, RejectsNonHexEscapes) {
+  // A sign or whitespace inside the two-character escape window must not be
+  // accepted as a valid percent-encoding; the sequence is passed through
+  // literally, matching decode_uri_component / decode_path_component.
+  EXPECT_EQ("%-1", decode_query_component("%-1", false));
+  EXPECT_EQ("%-0", decode_query_component("%-0", false));
+  EXPECT_EQ("%+5", decode_query_component("%+5", false));
+  EXPECT_EQ("% 5", decode_query_component("% 5", false));
+  // Well-formed escapes still decode.
+  EXPECT_EQ("-", decode_query_component("%2D", false));
+  EXPECT_EQ("A", decode_query_component("%41", false));
+}
+
 TEST(SanitizeFilenameTest, VariousPatterns) {
   // Path traversal
   EXPECT_EQ("passwd", httplib::sanitize_filename("../../../etc/passwd"));