| @@ -57,7 +57,8 @@ | |||||
| static const char json_null_str[] = "null"; | static const char json_null_str[] = "null"; | ||||
| static const int json_null_str_len = sizeof(json_null_str) - 1; | static const int json_null_str_len = sizeof(json_null_str) - 1; | ||||
| static const char json_inf_str[] = "Infinity"; | static const char json_inf_str[] = "Infinity"; | ||||
| static const int json_inf_str_len = sizeof(json_inf_str) - 1; | |||||
| static const char json_inf_str_lower[] = "infinity"; | |||||
| static const unsigned int json_inf_str_len = sizeof(json_inf_str) - 1; | |||||
| static const char json_nan_str[] = "NaN"; | static const char json_nan_str[] = "NaN"; | ||||
| static const int json_nan_str_len = sizeof(json_nan_str) - 1; | static const int json_nan_str_len = sizeof(json_nan_str) - 1; | ||||
| static const char json_true_str[] = "true"; | static const char json_true_str[] = "true"; | ||||
| @@ -383,40 +384,55 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| tok->depth--; | tok->depth--; | ||||
| goto redo_char; | goto redo_char; | ||||
| case json_tokener_state_inf: /* aka starts with 'i' */ | |||||
| case json_tokener_state_inf: /* aka starts with 'i' (or 'I', or "-i", or "-I") */ | |||||
| { | { | ||||
| size_t size_inf; | |||||
| /* If we were guaranteed to have len set, then we could (usually) handle | |||||
| * the entire "Infinity" check in a single strncmp (strncasecmp), but | |||||
| * since len might be -1 (i.e. "read until \0"), we need to check it | |||||
| * a character at a time. | |||||
| * Trying to handle it both ways would make this code considerably more | |||||
| * complicated with likely little performance benefit. | |||||
| */ | |||||
| int is_negative = 0; | int is_negative = 0; | ||||
| char *infbuf; | |||||
| const char *_json_inf_str = json_inf_str; | |||||
| if (!(tok->flags & JSON_TOKENER_STRICT)) | |||||
| _json_inf_str = json_inf_str_lower; | |||||
| printbuf_memappend_fast(tok->pb, &c, 1); | |||||
| size_inf = json_min(tok->st_pos+1, json_inf_str_len); | |||||
| infbuf = tok->pb->buf; | |||||
| if (*infbuf == '-') | |||||
| { | |||||
| infbuf++; | |||||
| is_negative = 1; | |||||
| } | |||||
| if ((!(tok->flags & JSON_TOKENER_STRICT) && | |||||
| strncasecmp(json_inf_str, infbuf, size_inf) == 0) || | |||||
| (strncmp(json_inf_str, infbuf, size_inf) == 0) | |||||
| ) | |||||
| /* Note: tok->st_pos must be 0 when state is set to json_tokener_state_inf */ | |||||
| while (tok->st_pos < (int)json_inf_str_len) | |||||
| { | { | ||||
| if (tok->st_pos == json_inf_str_len) | |||||
| char inf_char = *str; | |||||
| if (!(tok->flags & JSON_TOKENER_STRICT)) | |||||
| inf_char = tolower(*str); | |||||
| if (inf_char != _json_inf_str[tok->st_pos]) | |||||
| { | { | ||||
| current = json_object_new_double(is_negative | |||||
| ? -INFINITY : INFINITY); | |||||
| if(current == NULL) | |||||
| goto out; | |||||
| saved_state = json_tokener_state_finish; | |||||
| state = json_tokener_state_eatws; | |||||
| goto redo_char; | |||||
| tok->err = json_tokener_error_parse_unexpected; | |||||
| goto out; | |||||
| } | |||||
| tok->st_pos++; | |||||
| (void)ADVANCE_CHAR(str, tok); | |||||
| if (!PEEK_CHAR(c, tok)) | |||||
| { | |||||
| /* out of input chars, for now at least */ | |||||
| goto out; | |||||
| } | } | ||||
| } else { | |||||
| tok->err = json_tokener_error_parse_unexpected; | |||||
| goto out; | |||||
| } | } | ||||
| tok->st_pos++; | |||||
| /* We checked the full length of "Infinity", so create the object. | |||||
| * When handling -Infinity, the number parsing code will have dropped | |||||
| * the "-" into tok->pb for us, so check it now. | |||||
| */ | |||||
| if (printbuf_length(tok->pb) > 0 && *(tok->pb->buf) == '-') | |||||
| { | |||||
| is_negative = 1; | |||||
| } | |||||
| current = json_object_new_double(is_negative | |||||
| ? -INFINITY : INFINITY); | |||||
| if (current == NULL) | |||||
| goto out; | |||||
| saved_state = json_tokener_state_finish; | |||||
| state = json_tokener_state_eatws; | |||||
| goto redo_char; | |||||
| } | } | ||||
| break; | break; | ||||
| case json_tokener_state_null: /* aka starts with 'n' */ | case json_tokener_state_null: /* aka starts with 'n' */ | ||||
| @@ -934,7 +950,7 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, | |||||
| } | } | ||||
| if (!ADVANCE_CHAR(str, tok)) | if (!ADVANCE_CHAR(str, tok)) | ||||
| goto out; | goto out; | ||||
| } /* while(POP_CHAR) */ | |||||
| } /* while(PEEK_CHAR) */ | |||||
| out: | out: | ||||
| if (c && | if (c && | ||||