@@ -68,7 +68,8 @@ typedef enum /* type categories for datum_to_json */
68
68
69
69
static inline void json_lex (JsonLexContext * lex );
70
70
static inline void json_lex_string (JsonLexContext * lex );
71
- static inline void json_lex_number (JsonLexContext * lex , char * s , bool * num_err );
71
+ static inline void json_lex_number (JsonLexContext * lex , char * s ,
72
+ bool * num_err , int * total_len );
72
73
static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
73
74
static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
74
75
static void parse_object (JsonLexContext * lex , JsonSemAction * sem );
@@ -174,13 +175,20 @@ lex_expect(JsonParseContext ctx, JsonLexContext *lex, JsonTokenType token)
174
175
(c) == '_' || \
175
176
IS_HIGHBIT_SET(c))
176
177
177
- /* utility function to check if a string is a valid JSON number */
178
- extern bool
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
179
184
IsValidJsonNumber (const char * str , int len )
180
185
{
181
186
bool numeric_error ;
187
+ int total_len ;
182
188
JsonLexContext dummy_lex ;
183
189
190
+ if (len <= 0 )
191
+ return false;
184
192
185
193
/*
186
194
* json_lex_number expects a leading '-' to have been eaten already.
@@ -199,9 +207,9 @@ IsValidJsonNumber(const char *str, int len)
199
207
dummy_lex .input_length = len ;
200
208
}
201
209
202
- json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error );
210
+ json_lex_number (& dummy_lex , dummy_lex .input , & numeric_error , & total_len );
203
211
204
- return !numeric_error ;
212
+ return ( !numeric_error ) && ( total_len == dummy_lex . input_length ) ;
205
213
}
206
214
207
215
/*
@@ -622,7 +630,7 @@ json_lex(JsonLexContext *lex)
622
630
break ;
623
631
case '-' :
624
632
/* Negative number. */
625
- json_lex_number (lex , s + 1 , NULL );
633
+ json_lex_number (lex , s + 1 , NULL , NULL );
626
634
lex -> token_type = JSON_TOKEN_NUMBER ;
627
635
break ;
628
636
case '0' :
@@ -636,7 +644,7 @@ json_lex(JsonLexContext *lex)
636
644
case '8' :
637
645
case '9' :
638
646
/* Positive number. */
639
- json_lex_number (lex , s , NULL );
647
+ json_lex_number (lex , s , NULL , NULL );
640
648
lex -> token_type = JSON_TOKEN_NUMBER ;
641
649
break ;
642
650
default :
@@ -936,7 +944,7 @@ json_lex_string(JsonLexContext *lex)
936
944
lex -> token_terminator = s + 1 ;
937
945
}
938
946
939
- /*-------------------------------------------------------------------------
947
+ /*
940
948
* The next token in the input stream is known to be a number; lex it.
941
949
*
942
950
* In JSON, a number consists of four parts:
@@ -957,29 +965,30 @@ json_lex_string(JsonLexContext *lex)
957
965
* followed by at least one digit.)
958
966
*
959
967
* 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
961
969
* first character of the string if there is none.
962
970
*
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.
964
974
*/
965
975
static inline void
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 )
967
978
{
968
979
bool error = false;
969
- char * p ;
970
- int len ;
980
+ int len = s - lex -> input ;
971
981
972
- len = s - lex -> input ;
973
982
/* Part (1): leading sign indicator. */
974
983
/* Caller already did this for us; so do nothing. */
975
984
976
985
/* Part (2): parse main digit string. */
977
- if (* s == '0' )
986
+ if (len < lex -> input_length && * s == '0' )
978
987
{
979
988
s ++ ;
980
989
len ++ ;
981
990
}
982
- else if (* s >= '1' && * s <= '9' )
991
+ else if (len < lex -> input_length && * s >= '1' && * s <= '9' )
983
992
{
984
993
do
985
994
{
@@ -1034,18 +1043,23 @@ json_lex_number(JsonLexContext *lex, char *s, bool *num_err)
1034
1043
* here should be considered part of the token for error-reporting
1035
1044
* purposes.
1036
1045
*/
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 ++ )
1038
1047
error = true;
1039
1048
1049
+ if (total_len != NULL )
1050
+ * total_len = len ;
1051
+
1040
1052
if (num_err != NULL )
1041
1053
{
1042
- /* let the caller handle the error */
1054
+ /* let the caller handle any error */
1043
1055
* num_err = error ;
1044
1056
}
1045
1057
else
1046
1058
{
1059
+ /* return token endpoint */
1047
1060
lex -> prev_token_terminator = lex -> token_terminator ;
1048
- lex -> token_terminator = p ;
1061
+ lex -> token_terminator = s ;
1062
+ /* handle error if any */
1049
1063
if (error )
1050
1064
report_invalid_token (lex );
1051
1065
}
0 commit comments