@@ -68,7 +68,8 @@ typedef enum /* type categories for datum_to_json */
6868
6969static inline void json_lex (JsonLexContext * lex );
7070static 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 );
7273static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
7374static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
7475static void parse_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- 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
179184IsValidJsonNumber (const char * str , int len )
180185{
181186 bool numeric_error ;
187+ int total_len ;
182188 JsonLexContext dummy_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 */
965975static 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 )
967978{
968979 bool error = false;
969- char * p ;
970- int len ;
980+ int len = 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- else if (* s >= '1' && * s <= '9' )
991+ else if (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 handle the error */
1054+ /* let the caller handle any 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