@@ -76,7 +76,8 @@ typedef struct JsonAggState
76
76
77
77
static inline void json_lex (JsonLexContext * lex );
78
78
static inline void json_lex_string (JsonLexContext * lex );
79
- static inline void json_lex_number (JsonLexContext * lex , char * s , bool * num_err );
79
+ static inline void json_lex_number (JsonLexContext * lex , char * s ,
80
+ bool * num_err , int * total_len );
80
81
static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
81
82
static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
82
83
static void parse_object (JsonLexContext * lex , JsonSemAction * sem );
@@ -182,13 +183,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
182
183
(c) == '_' || \
183
184
IS_HIGHBIT_SET(c))
184
185
185
- /* utility function to check if a string is a valid JSON number */
186
- extern bool
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
187
192
IsValidJsonNumber (const char * str , int len )
188
193
{
189
194
bool numeric_error ;
195
+ int total_len ;
190
196
JsonLexContext dummy_lex ;
191
197
198
+ if (len <= 0 )
199
+ return false;
192
200
193
201
/*
194
202
* json_lex_number expects a leading '-' to have been eaten already.
@@ -207,9 +215,9 @@ IsValidJsonNumber(const char *str, int len)
207
215
dummy_lex .input_length = len ;
208
216
}
209
217
210
- json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error );
218
+ json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error , & total_len );
211
219
212
- return !numeric_error ;
220
+ return ( !numeric_error ) && ( total_len == dummy_lex . input_length ) ;
213
221
}
214
222
215
223
/*
@@ -669,7 +677,7 @@ json_lex(JsonLexContext *lex)
669
677
break ;
670
678
case '-' :
671
679
/* Negative number. */
672
- json_lex_number (lex , s + 1 , NULL );
680
+ json_lex_number (lex , s + 1 , NULL , NULL );
673
681
lex -> token_type = JSON_TOKEN_NUMBER ;
674
682
break ;
675
683
case '0' :
@@ -683,7 +691,7 @@ json_lex(JsonLexContext *lex)
683
691
case '8' :
684
692
case '9' :
685
693
/* Positive number. */
686
- json_lex_number (lex , s , NULL );
694
+ json_lex_number (lex , s , NULL , NULL );
687
695
lex -> token_type = JSON_TOKEN_NUMBER ;
688
696
break ;
689
697
default :
@@ -983,7 +991,7 @@ json_lex_string(JsonLexContext *lex)
983
991
lex -> token_terminator = s + 1 ;
984
992
}
985
993
986
- /*-------------------------------------------------------------------------
994
+ /*
987
995
* The next token in the input stream is known to be a number; lex it.
988
996
*
989
997
* In JSON, a number consists of four parts:
@@ -1004,29 +1012,30 @@ json_lex_string(JsonLexContext *lex)
1004
1012
* followed by at least one digit.)
1005
1013
*
1006
1014
* 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
1008
1016
* first character of the string if there is none.
1009
1017
*
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.
1011
1021
*/
1012
1022
static inline void
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 )
1014
1025
{
1015
1026
bool error = false;
1016
- char * p ;
1017
- int len ;
1027
+ int len = s - lex -> input ;
1018
1028
1019
- len = s - lex -> input ;
1020
1029
/* Part (1): leading sign indicator. */
1021
1030
/* Caller already did this for us; so do nothing. */
1022
1031
1023
1032
/* Part (2): parse main digit string. */
1024
- if (* s == '0' )
1033
+ if (len < lex -> input_length && * s == '0' )
1025
1034
{
1026
1035
s ++ ;
1027
1036
len ++ ;
1028
1037
}
1029
- else if (* s >= '1' && * s <= '9' )
1038
+ else if (len < lex -> input_length && * s >= '1' && * s <= '9' )
1030
1039
{
1031
1040
do
1032
1041
{
@@ -1081,18 +1090,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
1081
1090
* here should be considered part of the token for error-reporting
1082
1091
* purposes.
1083
1092
*/
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 ++ )
1085
1094
error = true;
1086
1095
1096
+ if (total_len != NULL )
1097
+ * total_len = len ;
1098
+
1087
1099
if (num_err != NULL )
1088
1100
{
1089
- /* let the caller handle the error */
1101
+ /* let the caller handle any error */
1090
1102
* num_err = error ;
1091
1103
}
1092
1104
else
1093
1105
{
1106
+ /* return token endpoint */
1094
1107
lex -> prev_token_terminator = lex -> token_terminator ;
1095
- lex -> token_terminator = p ;
1108
+ lex -> token_terminator = s ;
1109
+ /* handle error if any */
1096
1110
if (error )
1097
1111
report_invalid_token (lex );
1098
1112
}
0 commit comments