Skip to content

Commit 6600856

Browse files
committed
Avoid reading past datum end when parsing JSON.
Several loops in the JSON parser examined a byte in memory just before checking whether its address was in-bounds, so they could read one byte beyond the datum's allocation. A SIGSEGV is possible. New in 9.3, so no back-patch.
1 parent 3a5d0c5 commit 6600856

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/backend/utils/adt/json.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ json_lex(JsonLexContext *lex)
598598
* the whole word as an unexpected token, rather than just
599599
* some unintuitive prefix thereof.
600600
*/
601-
for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && p - s < lex->input_length - len; p++)
601+
for (p = s; p - s < lex->input_length - len && JSON_ALPHANUMERIC_CHAR(*p); p++)
602602
/* skip */ ;
603603

604604
/*
@@ -651,16 +651,21 @@ json_lex_string(JsonLexContext *lex)
651651
if (lex->strval != NULL)
652652
resetStringInfo(lex->strval);
653653

654+
Assert(lex->input_length > 0);
655+
s = lex->token_start;
654656
len = lex->token_start - lex->input;
655-
len++;
656-
for (s = lex->token_start + 1; *s != '"'; s++, len++)
657+
for (;;)
657658
{
659+
s++;
660+
len++;
658661
/* Premature end of the string. */
659662
if (len >= lex->input_length)
660663
{
661664
lex->token_terminator = s;
662665
report_invalid_token(lex);
663666
}
667+
else if (*s == '"')
668+
break;
664669
else if ((unsigned char) *s < 32)
665670
{
666671
/* Per RFC4627, these characters MUST be escaped. */
@@ -921,7 +926,7 @@ json_lex_number(JsonLexContext *lex, char *s)
921926
{
922927
s++;
923928
len++;
924-
} while (*s >= '0' && *s <= '9' && len < lex->input_length);
929+
} while (len < lex->input_length && *s >= '0' && *s <= '9');
925930
}
926931
else
927932
error = true;
@@ -939,7 +944,7 @@ json_lex_number(JsonLexContext *lex, char *s)
939944
{
940945
s++;
941946
len++;
942-
} while (*s >= '0' && *s <= '9' && len < lex->input_length);
947+
} while (len < lex->input_length && *s >= '0' && *s <= '9');
943948
}
944949
}
945950

@@ -970,7 +975,7 @@ json_lex_number(JsonLexContext *lex, char *s)
970975
* here should be considered part of the token for error-reporting
971976
* purposes.
972977
*/
973-
for (p = s; JSON_ALPHANUMERIC_CHAR(*p) && len < lex->input_length; p++, len++)
978+
for (p = s; len < lex->input_length && JSON_ALPHANUMERIC_CHAR(*p); p++, len++)
974979
error = true;
975980
lex->prev_token_terminator = lex->token_terminator;
976981
lex->token_terminator = p;
@@ -1138,8 +1143,8 @@ report_json_context(JsonLexContext *lex)
11381143
line_number = 1;
11391144
for (;;)
11401145
{
1141-
/* Always advance over newlines (context_end test is just paranoia) */
1142-
if (*context_start == '\n' && context_start < context_end)
1146+
/* Always advance over newlines */
1147+
if (context_start < context_end && *context_start == '\n')
11431148
{
11441149
context_start++;
11451150
line_start = context_start;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy