@@ -76,7 +76,8 @@ typedef struct JsonAggState
7676
7777static inline void json_lex (JsonLexContext * lex );
7878static 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 );
8081static inline void parse_scalar (JsonLexContext * lex , JsonSemAction * sem );
8182static void parse_object_field (JsonLexContext * lex , JsonSemAction * sem );
8283static void parse_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- 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
187192IsValidJsonNumber (const char * str , int len )
188193{
189194 bool numeric_error ;
195+ int total_len ;
190196 JsonLexContext dummy_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 */
10121022static 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 )
10141025{
10151026 bool error = false;
1016- char * p ;
1017- int len ;
1027+ int len = 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- else if (* s >= '1' && * s <= '9' )
1038+ else if (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 handle the error */
1101+ /* let the caller handle any 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