summaryrefslogtreecommitdiff
path: root/src/yajl_parser.c
diff options
context:
space:
mode:
authorGreg Olszewski <gno@gropeep.org>2010-10-17 17:05:01 -0700
committerLloyd Hilaiel <lloyd@hilaiel.com>2011-04-20 15:24:19 -0600
commit7852c0a1970b67c22b7b7bfeb29095bcc21ca12f (patch)
tree6c5ee341a57ddc31ea920eae720083d50b55436c /src/yajl_parser.c
parent986516e15b7b331a19fe317e2c828c5352d5b72e (diff)
downloadyajl-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.c55
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,