Skip to content

Commit

Permalink
Honor JSON_DECODE_INT_AS_REAL at lexical stage
Browse files Browse the repository at this point in the history
This has the consequence that numbers are never converted to integers
when JSON_DECODE_INT_AS_REAL is set, and thus it works correctly all
integers that are representable as double.

Fixes #212.
  • Loading branch information
akheron committed Dec 18, 2014
1 parent d799ee1 commit 5508ab4
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 16 deletions.
27 changes: 11 additions & 16 deletions src/load.c
Expand Up @@ -61,6 +61,7 @@ typedef struct {
typedef struct {
stream_t stream;
strbuffer_t saved_text;
size_t flags;
int token;
union {
struct {
Expand Down Expand Up @@ -507,7 +508,9 @@ static int lex_scan_number(lex_t *lex, int c, json_error_t *error)
goto out;
}

if(c != '.' && c != 'E' && c != 'e') {
if(!(lex->flags & JSON_DECODE_INT_AS_REAL) &&
c != '.' && c != 'E' && c != 'e')
{
json_int_t intval;

lex_unget_unsave(lex, c);
Expand Down Expand Up @@ -654,12 +657,13 @@ static char *lex_steal_string(lex_t *lex, size_t *out_len)
return result;
}

static int lex_init(lex_t *lex, get_func get, void *data)
static int lex_init(lex_t *lex, get_func get, size_t flags, void *data)
{
stream_init(&lex->stream, get, data);
if(strbuffer_init(&lex->saved_text))
return -1;

lex->flags = flags;
lex->token = TOKEN_INVALID;
return 0;
}
Expand Down Expand Up @@ -798,7 +802,6 @@ static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error)
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *json;
double value;

switch(lex->token) {
case TOKEN_STRING: {
Expand All @@ -821,15 +824,7 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
}

case TOKEN_INTEGER: {
if (flags & JSON_DECODE_INT_AS_REAL) {
if(jsonp_strtod(&lex->saved_text, &value)) {
error_set(error, lex, "real number overflow");
return NULL;
}
json = json_real(value);
} else {
json = json_integer(lex->value.integer);
}
json = json_integer(lex->value.integer);
break;
}

Expand Down Expand Up @@ -942,7 +937,7 @@ json_t *json_loads(const char *string, size_t flags, json_error_t *error)
stream_data.data = string;
stream_data.pos = 0;

if(lex_init(&lex, string_get, (void *)&stream_data))
if(lex_init(&lex, string_get, flags, (void *)&stream_data))
return NULL;

result = parse_json(&lex, flags, error);
Expand Down Expand Up @@ -987,7 +982,7 @@ json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t
stream_data.pos = 0;
stream_data.len = buflen;

if(lex_init(&lex, buffer_get, (void *)&stream_data))
if(lex_init(&lex, buffer_get, flags, (void *)&stream_data))
return NULL;

result = parse_json(&lex, flags, error);
Expand All @@ -1014,7 +1009,7 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
return NULL;
}

if(lex_init(&lex, (get_func)fgetc, input))
if(lex_init(&lex, (get_func)fgetc, flags, input))
return NULL;

result = parse_json(&lex, flags, error);
Expand Down Expand Up @@ -1095,7 +1090,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flag
return NULL;
}

if(lex_init(&lex, (get_func)callback_get, &stream_data))
if(lex_init(&lex, (get_func)callback_get, flags, &stream_data))
return NULL;

result = parse_json(&lex, flags, error);
Expand Down
14 changes: 14 additions & 0 deletions test/suites/api/test_load.c
Expand Up @@ -97,6 +97,8 @@ static void decode_int_as_real()
json_int_t expected;
#endif

char big[311];

json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
if (!json || !json_is_real(json) || json_real_value(json) != 42.0)
fail("json_load decode int as real failed - int");
Expand All @@ -113,6 +115,18 @@ static void decode_int_as_real()
fail("json_load decode int as real failed - expected imprecision");
json_decref(json);
#endif

/* 1E309 overflows. Here we create 1E309 as a decimal number, i.e.
1000...(309 zeroes)...0. */
big[0] = '1';
memset(big + 1, '0', 309);
big[310] = '\0';

json = json_loads(big, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
if (json || strcmp(error.text, "real number overflow") != 0)
fail("json_load decode int as real failed - expected overflow");
json_decref(json);

}

static void allow_nul()
Expand Down

0 comments on commit 5508ab4

Please sign in to comment.