From f81da5e57a2c85c283080be18d1bc5a94cd91345 Mon Sep 17 00:00:00 2001 From: Eric Haszlakiewicz Date: Mon, 27 Nov 2017 00:20:11 -0500 Subject: [PATCH] Rewrite the json_tokener_state_inf handling in json_tokener to be simpler, and avoid needless copying of the input into a temporary buffer. --- json_tokener.c | 74 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/json_tokener.c b/json_tokener.c index 4aaa89f..416058d 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -57,7 +57,8 @@ static const char json_null_str[] = "null"; static const int json_null_str_len = sizeof(json_null_str) - 1; 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 int json_nan_str_len = sizeof(json_nan_str) - 1; static const char json_true_str[] = "true"; @@ -383,40 +384,55 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, tok->depth--; 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; - 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; 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)) goto out; - } /* while(POP_CHAR) */ + } /* while(PEEK_CHAR) */ out: if (c && -- 2.49.0