Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1f2b195

Browse files
committed
Fix IsValidJsonNumber() to notice trailing non-alphanumeric garbage.
Commite09996f was one brick shy of a load: it didn't insistthat the detected JSON number be the whole of the supplied string.This allowed inputs such as "2016-01-01" to be misdetected as valid JSONnumbers. Per bug #13906 from Dmitry Ryabov.In passing, be more wary of zero-length input (I'm not sure this canhappen given current callers, but better safe than sorry), and do someminor cosmetic cleanup.
1 parent0b55fef commit1f2b195

File tree

3 files changed

+38
-24
lines changed

3 files changed

+38
-24
lines changed

‎contrib/hstore/expected/hstore.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,10 +1466,10 @@ select cast( hstore '"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=
14661466
{"b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4", "a key": "1"}
14671467
(1 row)
14681468

1469-
select hstore_to_json_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
1470-
hstore_to_json_loose
1471-
------------------------------------------------------------------------------------------
1472-
{"b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4, "a key": 1}
1469+
select hstore_to_json_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4, h=> "2016-01-01"');
1470+
hstore_to_json_loose
1471+
-------------------------------------------------------------------------------------------------------------
1472+
{"b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4, "h": "2016-01-01", "a key": 1}
14731473
(1 row)
14741474

14751475
create table test_json_agg (f1 text, f2 hstore);

‎contrib/hstore/sql/hstore.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ select count(*) from testhstore where h = 'pos=>98, line=>371, node=>CBA, indexe
334334
-- json
335335
select hstore_to_json('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
336336
select cast( hstore'"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4'as json);
337-
select hstore_to_json_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
337+
select hstore_to_json_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4, h=> "2016-01-01"');
338338

339339
createtabletest_json_agg (f1text, f2 hstore);
340340
insert into test_json_aggvalues ('rec1','"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4'),

‎src/backend/utils/adt/json.c

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ typedef enum/* type categories for datum_to_json */
6363

6464
staticinlinevoidjson_lex(JsonLexContext*lex);
6565
staticinlinevoidjson_lex_string(JsonLexContext*lex);
66-
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,bool*num_err);
66+
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,
67+
bool*num_err,int*total_len);
6768
staticinlinevoidparse_scalar(JsonLexContext*lex,JsonSemAction*sem);
6869
staticvoidparse_object_field(JsonLexContext*lex,JsonSemAction*sem);
6970
staticvoidparse_object(JsonLexContext*lex,JsonSemAction*sem);
@@ -166,13 +167,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
166167
(c) == '_' || \
167168
IS_HIGHBIT_SET(c))
168169

169-
/* utility function to check if a string is a valid JSON number */
170-
externbool
170+
/*
171+
* Utility function to check if a string is a valid JSON number.
172+
*
173+
* str is of length len, and need not be null-terminated.
174+
*/
175+
bool
171176
IsValidJsonNumber(constchar*str,intlen)
172177
{
173178
boolnumeric_error;
179+
inttotal_len;
174180
JsonLexContextdummy_lex;
175181

182+
if (len <=0)
183+
return false;
176184

177185
/*
178186
* json_lex_number expects a leading '-' to have been eaten already.
@@ -191,9 +199,9 @@ IsValidJsonNumber(const char *str, int len)
191199
dummy_lex.input_length=len;
192200
}
193201

194-
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
202+
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error,&total_len);
195203

196-
return !numeric_error;
204+
return(!numeric_error)&& (total_len==dummy_lex.input_length);
197205
}
198206

199207
/*
@@ -610,7 +618,7 @@ json_lex(JsonLexContext *lex)
610618
break;
611619
case'-':
612620
/* Negative number. */
613-
json_lex_number(lex,s+1,NULL);
621+
json_lex_number(lex,s+1,NULL,NULL);
614622
lex->token_type=JSON_TOKEN_NUMBER;
615623
break;
616624
case'0':
@@ -624,7 +632,7 @@ json_lex(JsonLexContext *lex)
624632
case'8':
625633
case'9':
626634
/* Positive number. */
627-
json_lex_number(lex,s,NULL);
635+
json_lex_number(lex,s,NULL,NULL);
628636
lex->token_type=JSON_TOKEN_NUMBER;
629637
break;
630638
default:
@@ -919,7 +927,7 @@ json_lex_string(JsonLexContext *lex)
919927
lex->token_terminator=s+1;
920928
}
921929

922-
/*-------------------------------------------------------------------------
930+
/*
923931
* The next token in the input stream is known to be a number; lex it.
924932
*
925933
* In JSON, a number consists of four parts:
@@ -940,29 +948,30 @@ json_lex_string(JsonLexContext *lex)
940948
* followed by at least one digit.)
941949
*
942950
* The 's' argument to this function points to the ostensible beginning
943-
* of part 2 - i.e. the character after any optional minus sign,and the
951+
* of part 2 - i.e. the character after any optional minus sign,or the
944952
* first character of the string if there is none.
945953
*
946-
*-------------------------------------------------------------------------
954+
* If num_err is not NULL, we return an error flag to *num_err rather than
955+
* raising an error for a badly-formed number. Also, if total_len is not NULL
956+
* the distance from lex->input to the token end+1 is returned to *total_len.
947957
*/
948958
staticinlinevoid
949-
json_lex_number(JsonLexContext*lex,char*s,bool*num_err)
959+
json_lex_number(JsonLexContext*lex,char*s,
960+
bool*num_err,int*total_len)
950961
{
951962
boolerror= false;
952-
char*p;
953-
intlen;
963+
intlen=s-lex->input;
954964

955-
len=s-lex->input;
956965
/* Part (1): leading sign indicator. */
957966
/* Caller already did this for us; so do nothing. */
958967

959968
/* Part (2): parse main digit string. */
960-
if (*s=='0')
969+
if (len<lex->input_length&&*s=='0')
961970
{
962971
s++;
963972
len++;
964973
}
965-
elseif (*s >='1'&&*s <='9')
974+
elseif (len<lex->input_length&&*s >='1'&&*s <='9')
966975
{
967976
do
968977
{
@@ -1017,18 +1026,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
10171026
* here should be considered part of the token for error-reporting
10181027
* purposes.
10191028
*/
1020-
for (p=s;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*p);p++,len++)
1029+
for (;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*s);s++,len++)
10211030
error= true;
10221031

1032+
if (total_len!=NULL)
1033+
*total_len=len;
1034+
10231035
if (num_err!=NULL)
10241036
{
1025-
/* let the caller handlethe error */
1037+
/* let the caller handleany error */
10261038
*num_err=error;
10271039
}
10281040
else
10291041
{
1042+
/* return token endpoint */
10301043
lex->prev_token_terminator=lex->token_terminator;
1031-
lex->token_terminator=p;
1044+
lex->token_terminator=s;
1045+
/* handle error if any */
10321046
if (error)
10331047
report_invalid_token(lex);
10341048
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp