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

Commite6ecc93

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 parent7d17e68 commite6ecc93

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
@@ -76,7 +76,8 @@ typedef struct JsonAggState
7676

7777
staticinlinevoidjson_lex(JsonLexContext*lex);
7878
staticinlinevoidjson_lex_string(JsonLexContext*lex);
79-
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,bool*num_err);
79+
staticinlinevoidjson_lex_number(JsonLexContext*lex,char*s,
80+
bool*num_err,int*total_len);
8081
staticinlinevoidparse_scalar(JsonLexContext*lex,JsonSemAction*sem);
8182
staticvoidparse_object_field(JsonLexContext*lex,JsonSemAction*sem);
8283
staticvoidparse_object(JsonLexContext*lex,JsonSemAction*sem);
@@ -182,13 +183,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
182183
(c) == '_' || \
183184
IS_HIGHBIT_SET(c))
184185

185-
/* utility function to check if a string is a valid JSON number */
186-
externbool
186+
/*
187+
* Utility function to check if a string is a valid JSON number.
188+
*
189+
* str is of length len, and need not be null-terminated.
190+
*/
191+
bool
187192
IsValidJsonNumber(constchar*str,intlen)
188193
{
189194
boolnumeric_error;
195+
inttotal_len;
190196
JsonLexContextdummy_lex;
191197

198+
if (len <=0)
199+
return false;
192200

193201
/*
194202
* json_lex_number expects a leading '-' to have been eaten already.
@@ -207,9 +215,9 @@ IsValidJsonNumber(const char *str, int len)
207215
dummy_lex.input_length=len;
208216
}
209217

210-
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error);
218+
json_lex_number(&dummy_lex,dummy_lex.input,&numeric_error,&total_len);
211219

212-
return !numeric_error;
220+
return(!numeric_error)&& (total_len==dummy_lex.input_length);
213221
}
214222

215223
/*
@@ -669,7 +677,7 @@ json_lex(JsonLexContext *lex)
669677
break;
670678
case'-':
671679
/* Negative number. */
672-
json_lex_number(lex,s+1,NULL);
680+
json_lex_number(lex,s+1,NULL,NULL);
673681
lex->token_type=JSON_TOKEN_NUMBER;
674682
break;
675683
case'0':
@@ -683,7 +691,7 @@ json_lex(JsonLexContext *lex)
683691
case'8':
684692
case'9':
685693
/* Positive number. */
686-
json_lex_number(lex,s,NULL);
694+
json_lex_number(lex,s,NULL,NULL);
687695
lex->token_type=JSON_TOKEN_NUMBER;
688696
break;
689697
default:
@@ -983,7 +991,7 @@ json_lex_string(JsonLexContext *lex)
983991
lex->token_terminator=s+1;
984992
}
985993

986-
/*-------------------------------------------------------------------------
994+
/*
987995
* The next token in the input stream is known to be a number; lex it.
988996
*
989997
* In JSON, a number consists of four parts:
@@ -1004,29 +1012,30 @@ json_lex_string(JsonLexContext *lex)
10041012
* followed by at least one digit.)
10051013
*
10061014
* The 's' argument to this function points to the ostensible beginning
1007-
* of part 2 - i.e. the character after any optional minus sign,and the
1015+
* of part 2 - i.e. the character after any optional minus sign,or the
10081016
* first character of the string if there is none.
10091017
*
1010-
*-------------------------------------------------------------------------
1018+
* If num_err is not NULL, we return an error flag to *num_err rather than
1019+
* raising an error for a badly-formed number. Also, if total_len is not NULL
1020+
* the distance from lex->input to the token end+1 is returned to *total_len.
10111021
*/
10121022
staticinlinevoid
1013-
json_lex_number(JsonLexContext*lex,char*s,bool*num_err)
1023+
json_lex_number(JsonLexContext*lex,char*s,
1024+
bool*num_err,int*total_len)
10141025
{
10151026
boolerror= false;
1016-
char*p;
1017-
intlen;
1027+
intlen=s-lex->input;
10181028

1019-
len=s-lex->input;
10201029
/* Part (1): leading sign indicator. */
10211030
/* Caller already did this for us; so do nothing. */
10221031

10231032
/* Part (2): parse main digit string. */
1024-
if (*s=='0')
1033+
if (len<lex->input_length&&*s=='0')
10251034
{
10261035
s++;
10271036
len++;
10281037
}
1029-
elseif (*s >='1'&&*s <='9')
1038+
elseif (len<lex->input_length&&*s >='1'&&*s <='9')
10301039
{
10311040
do
10321041
{
@@ -1081,18 +1090,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
10811090
* here should be considered part of the token for error-reporting
10821091
* purposes.
10831092
*/
1084-
for (p=s;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*p);p++,len++)
1093+
for (;len<lex->input_length&&JSON_ALPHANUMERIC_CHAR(*s);s++,len++)
10851094
error= true;
10861095

1096+
if (total_len!=NULL)
1097+
*total_len=len;
1098+
10871099
if (num_err!=NULL)
10881100
{
1089-
/* let the caller handlethe error */
1101+
/* let the caller handleany error */
10901102
*num_err=error;
10911103
}
10921104
else
10931105
{
1106+
/* return token endpoint */
10941107
lex->prev_token_terminator=lex->token_terminator;
1095-
lex->token_terminator=p;
1108+
lex->token_terminator=s;
1109+
/* handle error if any */
10961110
if (error)
10971111
report_invalid_token(lex);
10981112
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp