diff options
author | Greg Olszewski <gno@gropeep.org> | 2010-10-17 17:05:01 -0700 |
---|---|---|
committer | Lloyd Hilaiel <lloyd@hilaiel.com> | 2011-04-20 15:24:19 -0600 |
commit | 7852c0a1970b67c22b7b7bfeb29095bcc21ca12f (patch) | |
tree | 6c5ee341a57ddc31ea920eae720083d50b55436c /src/yajl_parser.c | |
parent | 986516e15b7b331a19fe317e2c828c5352d5b72e (diff) | |
download | yajl-7852c0a1970b67c22b7b7bfeb29095bcc21ca12f.tar.gz |
o closes #5 - replace strtol with own implementation, uses pascal strings.
o issue #6 - check a few malloc error cases.
Signed-off-by: Lloyd Hilaiel <lloyd@hilaiel.com>
Diffstat (limited to 'src/yajl_parser.c')
-rw-r--r-- | src/yajl_parser.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/src/yajl_parser.c b/src/yajl_parser.c index aee1198..aa51ce9 100644 --- a/src/yajl_parser.c +++ b/src/yajl_parser.c @@ -44,6 +44,31 @@ #include <assert.h> #include <math.h> +#define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10)) + + /* same semantics as strtol */ +static long long +yajl_parse_integer(const unsigned char *number, unsigned int length) +{ + long long ret = 0; + long sign = 1; + const unsigned char *pos = number; + if (*pos == '-') { pos++; sign = -1; } + if (*pos == '+') { pos++; } + + while (pos < number + length) { + + if ( ret > MAX_VALUE_TO_MULTIPLY ) { + errno = ERANGE; + return sign == 1 ? LLONG_MAX : LLONG_MIN; + } + ret *= 10; + ret += (*pos++ - '0'); + } + + return sign * ret; +} + unsigned char * yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLen, int verbose) @@ -74,6 +99,7 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, memneeded += strlen(errorText); } str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2); + if (!str) return NULL; str[0] = 0; strcat((char *) str, errorType); strcat((char *) str, " error"); @@ -114,10 +140,12 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, YA_MALLOC(&(hand->alloc), (unsigned int)(strlen((char *) str) + strlen((char *) text) + strlen(arrow) + 1)); - newStr[0] = 0; - strcat((char *) newStr, (char *) str); - strcat((char *) newStr, text); - strcat((char *) newStr, arrow); + if (newStr) { + newStr[0] = 0; + strcat((char *) newStr, (char *) str); + strcat((char *) newStr, text); + strcat((char *) newStr, arrow); + } YA_FREE(&(hand->alloc), str); str = (unsigned char *) newStr; } @@ -258,29 +286,14 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, stateToPush = yajl_state_array_start; break; case yajl_tok_integer: - /* - * note. strtol does not respect the length of - * the lexical token. in a corner case where the - * lexed number is a integer with a trailing zero, - * immediately followed by the end of buffer, - * sscanf could run off into oblivion and cause a - * crash. for this reason we copy the integer - * (and doubles), into our parse buffer (the same - * one used for unescaping strings), before - * calling strtol. yajl_buf ensures null padding, - * so we're safe. - */ if (hand->callbacks) { if (hand->callbacks->yajl_number) { _CC_CHK(hand->callbacks->yajl_number( hand->ctx,(const char *) buf, bufLen)); } else if (hand->callbacks->yajl_integer) { long long int i = 0; - yajl_buf_clear(hand->decodeBuf); - yajl_buf_append(hand->decodeBuf, buf, bufLen); - buf = yajl_buf_data(hand->decodeBuf); - i = strtoll((const char *) buf, NULL, 10); - if ((i == LONG_MIN || i == LONG_MAX) && + i = yajl_parse_integer(buf, bufLen); + if ((i == LLONG_MIN || i == LLONG_MAX) && errno == ERANGE) { yajl_bs_set(hand->stateStack, |