*** a/src/backend/utils/adt/json.c --- b/src/backend/utils/adt/json.c *************** *** 598,604 **** json_lex(JsonLexContext *lex) * the whole word as an unexpected token, rather than just * some unintuitive prefix thereof. */ ! for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && p - s < lex->input_length - len; p++) /* skip */ ; /* --- 598,604 ---- * the whole word as an unexpected token, rather than just * some unintuitive prefix thereof. */ ! for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++) /* skip */ ; /* *************** *** 650,665 **** json_lex_string(JsonLexContext *lex) if (lex->strval != NULL) resetStringInfo(lex->strval); len = lex->token_start - lex->input; ! len++; ! for (s = lex->token_start + 1; *s != '"'; s++, len++) { /* Premature end of the string. */ if (len >= lex->input_length) { lex->token_terminator = s; report_invalid_token(lex); } else if ((unsigned char) *s < 32) { /* Per RFC4627, these characters MUST be escaped. */ --- 650,670 ---- if (lex->strval != NULL) resetStringInfo(lex->strval); + Assert(lex->input_length > 0); + s = lex->token_start; len = lex->token_start - lex->input; ! for (;;) { + s++; + len++; /* Premature end of the string. */ if (len >= lex->input_length) { lex->token_terminator = s; report_invalid_token(lex); } + else if (*s == '"') + break; else if ((unsigned char) *s < 32) { /* Per RFC4627, these characters MUST be escaped. */ *************** *** 843,849 **** json_lex_number(JsonLexContext *lex, char *s) { s++; len++; ! } while (*s >= '0' && *s <= '9' && len < lex->input_length); } else error = true; --- 848,854 ---- { s++; len++; ! } while (len < lex->input_length && *s >= '0' && *s <= '9'); } else error = true; *************** *** 861,867 **** json_lex_number(JsonLexContext *lex, char *s) { s++; len++; ! } while (*s >= '0' && *s <= '9' && len < lex->input_length); } } --- 866,872 ---- { s++; len++; ! } while (len < lex->input_length && *s >= '0' && *s <= '9'); } } *************** *** 892,898 **** json_lex_number(JsonLexContext *lex, char *s) * here should be considered part of the token for error-reporting * purposes. */ ! for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && len < lex->input_length; p++, len++) error = true; lex->prev_token_terminator = lex->token_terminator; lex->token_terminator = p; --- 897,903 ---- * here should be considered part of the token for error-reporting * purposes. */ ! for (p = s; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*p); p++, len++) error = true; lex->prev_token_terminator = lex->token_terminator; lex->token_terminator = p; *************** *** 1060,1067 **** report_json_context(JsonLexContext *lex) line_number = 1; for (;;) { ! /* Always advance over newlines (context_end test is just paranoia) */ ! if (*context_start == '\n' && context_start < context_end) { context_start++; line_start = context_start; --- 1065,1072 ---- line_number = 1; for (;;) { ! /* Always advance over newlines */ ! if (context_start < context_end && *context_start == '\n') { context_start++; line_start = context_start;