]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
*) core: make ap_escape_quotes() work correctly on strings
authorStefan Eissing <icing@apache.org>
Wed, 6 Apr 2022 09:17:42 +0000 (09:17 +0000)
committerStefan Eissing <icing@apache.org>
Wed, 6 Apr 2022 09:17:42 +0000 (09:17 +0000)
     with more than MAX_INT/2 characters, counting quotes double.
     Credit to <generalbugs@zippenhop.com> for finding this.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1899609 13f79535-47bb-0310-9956-ffa450edef68

changes-entries/core_ap_escape_quotes.txt [new file with mode: 0644]
server/util.c
test/unit/util.c

diff --git a/changes-entries/core_ap_escape_quotes.txt b/changes-entries/core_ap_escape_quotes.txt
new file mode 100644 (file)
index 0000000..f83410a
--- /dev/null
@@ -0,0 +1,4 @@
+  *) core: make ap_escape_quotes() work correctly on strings
+     with more than MAX_INT/2 characters, counting quotes double.
+     Credit to <generalbugs@zippenhop.com> for finding this.
+     [Stefan Eissing]
\ No newline at end of file
index 771ba7b16f3047c1d5eb1f15e95492f0a442b08d..420615a41a5de97a10f4a1442e5ce97dc3e82cbc 100644 (file)
@@ -2615,7 +2615,7 @@ AP_DECLARE(void) ap_content_type_tolower(char *str)
  */
 AP_DECLARE(char *) ap_escape_quotes(apr_pool_t *p, const char *instring)
 {
-    int newlen = 0;
+    apr_ssize_t extra = 0;
     const char *inchr = instring;
     char *outchr, *outstring;
 
@@ -2624,9 +2624,8 @@ AP_DECLARE(char *) ap_escape_quotes(apr_pool_t *p, const char *instring)
      * string up by an extra byte each time we find an unescaped ".
      */
     while (*inchr != '\0') {
-        newlen++;
         if (*inchr == '"') {
-            newlen++;
+            extra++;
         }
         /*
          * If we find a slosh, and it's not the last byte in the string,
@@ -2634,11 +2633,15 @@ AP_DECLARE(char *) ap_escape_quotes(apr_pool_t *p, const char *instring)
          */
         else if ((*inchr == '\\') && (inchr[1] != '\0')) {
             inchr++;
-            newlen++;
         }
         inchr++;
     }
-    outstring = apr_palloc(p, newlen + 1);
+
+    if (!extra) {
+        return apr_pstrdup(p, instring);
+    }
+
+    outstring = apr_palloc(p, (inchr - instring) + extra + 1);
     inchr = instring;
     outchr = outstring;
     /*
index 5cadfd89ba1137439a12a4ab7e10a463fc8d5c0b..c9dec41a18e4a603729bafdd3c1ef058630e628d 100644 (file)
@@ -79,6 +79,41 @@ HTTPD_START_LOOP_TEST(find_token_correctly_parses_token_list, ap_test_token_case
 }
 END_TEST
 
+
+/*
+ * ap_escape_quotes()
+ */
+
+struct ap_escape_quotes_case {
+    const char *input;
+    const char *expected;
+};
+
+#define ESCQ    "\\\""
+
+const struct ap_escape_quotes_case ap_test_escape_quotes_cases[] = {
+    { "one", "one" },
+    { "o\"ne", "o"ESCQ"ne" },
+    { "o"ESCQ"ne", "o"ESCQ"ne" },
+    { "one\\", "one\\" },
+    { "o\\ne", "o\\ne" },
+    { "o\\"ESCQ"ne", "o\\\\"ESCQ"ne" }, /* 1st \ escapes 2nd, following '"' needs \ */
+};
+
+const size_t ap_test_escape_quotes_cases_len = sizeof(ap_test_escape_quotes_cases) /
+    sizeof(ap_test_escape_quotes_cases[0]);
+
+HTTPD_START_LOOP_TEST(check_escape_quotes, ap_test_escape_quotes_cases_len)
+{
+    const struct ap_escape_quotes_case *c = &ap_test_escape_quotes_cases[_i];
+    const char *result;
+
+    result = ap_escape_quotes(g_pool, c->input);
+    ck_assert_str_eq(result, c->expected);
+}
+END_TEST
+
+
 /*
  * Test Case Boilerplate
  */