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

Commitaa223a0

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 parent95a2cca commitaa223a0

File tree

3 files changed

+43
-29
lines changed

3 files changed

+43
-29
lines changed

‎contrib/hstore/expected/hstore.out

Lines changed: 8 additions & 8 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
select hstore_to_jsonb('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
@@ -1484,10 +1484,10 @@ select cast( hstore '"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=
14841484
{"b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4", "a key": "1"}
14851485
(1 row)
14861486

1487-
select hstore_to_jsonb_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
1488-
hstore_to_jsonb_loose
1489-
---------------------------------------------------------------------------------------
1490-
{"b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 23450, "a key": 1}
1487+
select hstore_to_jsonb_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4, h=> "2016-01-01"');
1488+
hstore_to_jsonb_loose
1489+
----------------------------------------------------------------------------------------------------------
1490+
{"b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 23450, "h": "2016-01-01", "a key": 1}
14911491
(1 row)
14921492

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

‎contrib/hstore/sql/hstore.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,11 @@ select count(*) from testhstore where h = 'pos=>98, line=>371, node=>CBA, indexe
334334
-- json and jsonb
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
select hstore_to_jsonb('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
340340
select cast( hstore'"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4'as jsonb);
341-
select hstore_to_jsonb_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4');
341+
select hstore_to_jsonb_loose('"a key" =>1, b => t, c => null, d=> 12345, e => 012345, f=> 1.234, g=> 2.345e+4, h=> "2016-01-01"');
342342

343343
createtabletest_json_agg (f1text, f2 hstore);
344344
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
@@ -68,7 +68,8 @@ typedef enum/* type categories for datum_to_json */
6868

6969
staticinlinevoidjson_lex(JsonLexContext*lex);
7070
staticinlinevoidjson_lex_string(JsonLexContext*lex);
71-
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,bool*num_err);
71+
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,
72+
bool*num_err,int*total_len);
7273
staticinlinevoidparse_scalar(JsonLexContext*lex,JsonSemAction*sem);
7374
staticvoidparse_object_field(JsonLexContext*lex,JsonSemAction*sem);
7475
staticvoidparse_object(JsonLexContext*lex,JsonSemAction*sem);
@@ -174,13 +175,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
174175
(c) == '_' || \
175176
IS_HIGHBIT_SET(c))
176177

177-
/* utility function to check if a string is a valid JSON number */
178-
externbool
178+
/*
179+
* Utility function to check if a string is a valid JSON number.
180+
*
181+
* str is of length len, and need not be null-terminated.
182+
*/
183+
bool
179184
IsValidJsonNumber(constchar*str,intlen)
180185
{
181186
boolnumeric_error;
187+
inttotal_len;
182188
JsonLexContextdummy_lex;
183189

190+
if (len <=0)
191+
return false;
184192

185193
/*
186194
* json_lex_number expects a leading '-' to have been eaten already.
@@ -199,9 +207,9 @@ IsValidJsonNumber(const char *str, int len)
199207
dummy_lex.input_length=len;
200208
}
201209

202-
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
210+
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error,&total_len);
203211

204-
return !numeric_error;
212+
return(!numeric_error)&& (total_len==dummy_lex.input_length);
205213
}
206214

207215
/*
@@ -622,7 +630,7 @@ json_lex(JsonLexContext *lex)
622630
break;
623631
case'-':
624632
/* Negative number. */
625-
json_lex_number(lex,s+1,NULL);
633+
json_lex_number(lex,s+1,NULL,NULL);
626634
lex->token_type=JSON_TOKEN_NUMBER;
627635
break;
628636
case'0':
@@ -636,7 +644,7 @@ json_lex(JsonLexContext *lex)
636644
case'8':
637645
case'9':
638646
/* Positive number. */
639-
json_lex_number(lex,s,NULL);
647+
json_lex_number(lex,s,NULL,NULL);
640648
lex->token_type=JSON_TOKEN_NUMBER;
641649
break;
642650
default:
@@ -936,7 +944,7 @@ json_lex_string(JsonLexContext *lex)
936944
lex->token_terminator=s+1;
937945
}
938946

939-
/*-------------------------------------------------------------------------
947+
/*
940948
* The next token in the input stream is known to be a number; lex it.
941949
*
942950
* In JSON, a number consists of four parts:
@@ -957,29 +965,30 @@ json_lex_string(JsonLexContext *lex)
957965
* followed by at least one digit.)
958966
*
959967
* The 's' argument to this function points to the ostensible beginning
960-
* of part 2 - i.e. the character after any optional minus sign,and the
968+
* of part 2 - i.e. the character after any optional minus sign,or the
961969
* first character of the string if there is none.
962970
*
963-
*-------------------------------------------------------------------------
971+
* If num_err is not NULL, we return an error flag to *num_err rather than
972+
* raising an error for a badly-formed number. Also, if total_len is not NULL
973+
* the distance from lex->input to the token end+1 is returned to *total_len.
964974
*/
965975
staticinlinevoid
966-
json_lex_number(JsonLexContext*lex,char*s,bool*num_err)
976+
json_lex_number(JsonLexContext*lex,char*s,
977+
bool*num_err,int*total_len)
967978
{
968979
boolerror= false;
969-
char*p;
970-
intlen;
980+
intlen=s-lex->input;
971981

972-
len=s-lex->input;
973982
/* Part (1): leading sign indicator. */
974983
/* Caller already did this for us; so do nothing. */
975984

976985
/* Part (2): parse main digit string. */
977-
if (*s=='0')
986+
if (len<lex->input_length&&*s=='0')
978987
{
979988
s++;
980989
len++;
981990
}
982-
elseif (*s >='1'&&*s <='9')
991+
elseif (len<lex->input_length&&*s >='1'&&*s <='9')
983992
{
984993
do
985994
{
@@ -1034,18 +1043,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
10341043
* here should be considered part of the token for error-reporting
10351044
* purposes.
10361045
*/
1037-
for (p=s;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*p);p++,len++)
1046+
for (;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*s);s++,len++)
10381047
error= true;
10391048

1049+
if (total_len!=NULL)
1050+
*total_len=len;
1051+
10401052
if (num_err!=NULL)
10411053
{
1042-
/* let the caller handlethe error */
1054+
/* let the caller handleany error */
10431055
*num_err=error;
10441056
}
10451057
else
10461058
{
1059+
/* return token endpoint */
10471060
lex->prev_token_terminator=lex->token_terminator;
1048-
lex->token_terminator=p;
1061+
lex->token_terminator=s;
1062+
/* handle error if any */
10491063
if (error)
10501064
report_invalid_token(lex);
10511065
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp