@@ -63,7 +63,8 @@ typedef enum /* type categories for datum_to_json */
63
63
64
64
static inline void json_lex (JsonLexContext * lex );
65
65
static inline void json_lex_string (JsonLexContext * lex );
66
- static inline void json_lex_number (JsonLexContext * lex , char * s , bool * num_err );
66
+ static inline void json_lex_number (JsonLexContext * lex , char * s ,
67
+ bool * num_err , int * total_len );
67
68
static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
68
69
static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
69
70
static void parse_object (JsonLexContext * lex , JsonSemAction * sem );
@@ -166,13 +167,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
166
167
(c) == '_' || \
167
168
IS_HIGHBIT_SET(c))
168
169
169
- /* utility function to check if a string is a valid JSON number */
170
- extern bool
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
171
176
IsValidJsonNumber (const char * str , int len )
172
177
{
173
178
bool numeric_error ;
179
+ int total_len ;
174
180
JsonLexContext dummy_lex ;
175
181
182
+ if (len <= 0 )
183
+ return false;
176
184
177
185
/*
178
186
* json_lex_number expects a leading '-' to have been eaten already.
@@ -191,9 +199,9 @@ IsValidJsonNumber(const char *str, int len)
191
199
dummy_lex .input_length = len ;
192
200
}
193
201
194
- json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error );
202
+ json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error , & total_len );
195
203
196
- return !numeric_error ;
204
+ return ( !numeric_error ) && ( total_len == dummy_lex . input_length ) ;
197
205
}
198
206
199
207
/*
@@ -610,7 +618,7 @@ json_lex(JsonLexContext *lex)
610
618
break ;
611
619
case '-' :
612
620
/* Negative number. */
613
- json_lex_number (lex , s + 1 , NULL );
621
+ json_lex_number (lex , s + 1 , NULL , NULL );
614
622
lex -> token_type = JSON_TOKEN_NUMBER ;
615
623
break ;
616
624
case '0' :
@@ -624,7 +632,7 @@ json_lex(JsonLexContext *lex)
624
632
case '8' :
625
633
case '9' :
626
634
/* Positive number. */
627
- json_lex_number (lex , s , NULL );
635
+ json_lex_number (lex , s , NULL , NULL );
628
636
lex -> token_type = JSON_TOKEN_NUMBER ;
629
637
break ;
630
638
default :
@@ -919,7 +927,7 @@ json_lex_string(JsonLexContext *lex)
919
927
lex -> token_terminator = s + 1 ;
920
928
}
921
929
922
- /*-------------------------------------------------------------------------
930
+ /*
923
931
* The next token in the input stream is known to be a number; lex it.
924
932
*
925
933
* In JSON, a number consists of four parts:
@@ -940,29 +948,30 @@ json_lex_string(JsonLexContext *lex)
940
948
* followed by at least one digit.)
941
949
*
942
950
* 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
944
952
* first character of the string if there is none.
945
953
*
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.
947
957
*/
948
958
static inline void
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 )
950
961
{
951
962
bool error = false;
952
- char * p ;
953
- int len ;
963
+ int len = s - lex -> input ;
954
964
955
- len = s - lex -> input ;
956
965
/* Part (1): leading sign indicator. */
957
966
/* Caller already did this for us; so do nothing. */
958
967
959
968
/* Part (2): parse main digit string. */
960
- if (* s == '0' )
969
+ if (len < lex -> input_length && * s == '0' )
961
970
{
962
971
s ++ ;
963
972
len ++ ;
964
973
}
965
- else if (* s >= '1' && * s <= '9' )
974
+ else if (len < lex -> input_length && * s >= '1' && * s <= '9' )
966
975
{
967
976
do
968
977
{
@@ -1017,18 +1026,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
1017
1026
* here should be considered part of the token for error-reporting
1018
1027
* purposes.
1019
1028
*/
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 ++ )
1021
1030
error = true;
1022
1031
1032
+ if (total_len != NULL )
1033
+ * total_len = len ;
1034
+
1023
1035
if (num_err != NULL )
1024
1036
{
1025
- /* let the caller handle the error */
1037
+ /* let the caller handle any error */
1026
1038
* num_err = error ;
1027
1039
}
1028
1040
else
1029
1041
{
1042
+ /* return token endpoint */
1030
1043
lex -> prev_token_terminator = lex -> token_terminator ;
1031
- lex -> token_terminator = p ;
1044
+ lex -> token_terminator = s ;
1045
+ /* handle error if any */
1032
1046
if (error )
1033
1047
report_invalid_token (lex );
1034
1048
}
0 commit comments