Fix out-of-bounds read in json_lex_string
authorJohn Naylor <john.naylor@postgresql.org>
Tue, 12 Jul 2022 04:13:41 +0000 (11:13 +0700)
committerJohn Naylor <john.naylor@postgresql.org>
Tue, 12 Jul 2022 04:25:47 +0000 (11:25 +0700)
Commit 3838fa269 added a lookahead loop to allow building strings multiple
bytes at a time. This loop could exit because it reached the end of input,
yet did not check for that before checking if we reached the end of a
valid string. To fix, put the end of string check back in the outer loop.

Per Valgrind animal skink

src/common/jsonapi.c

index 694417bb388e731a5a3ba04f808e74542020c693..fefd1d24d9060896fff6e888ef409406ad7d93bc 100644 (file)
@@ -686,6 +686,8 @@ json_lex_string(JsonLexContext *lex)
                        lex->token_terminator = s;
                        return JSON_INVALID_TOKEN;
                }
+               else if (*s == '"')
+                       break;
                else if (*s == '\\')
                {
                        /* OK, we have an escape character. */
@@ -870,14 +872,6 @@ json_lex_string(JsonLexContext *lex)
                        if (lex->strval != NULL)
                                appendBinaryStringInfo(lex->strval, s, p - s);
 
-                       if (*p == '"')
-                       {
-                               /* Hooray, we found the end of the string! */
-                               lex->prev_token_terminator = lex->token_terminator;
-                               lex->token_terminator = p + 1;
-                               return JSON_SUCCESS;
-                       }
-
                        /*
                         * s will be incremented at the top of the loop, so set it to just
                         * behind our lookahead position
@@ -885,6 +879,14 @@ json_lex_string(JsonLexContext *lex)
                        s = p - 1;
                }
        }
+
+       if (hi_surrogate != -1)
+               return JSON_UNICODE_LOW_SURROGATE;
+
+       /* Hooray, we found the end of the string! */
+       lex->prev_token_terminator = lex->token_terminator;
+       lex->token_terminator = s + 1;
+       return JSON_SUCCESS;
 }
 
 /*