load: Check for integer and real overlfows and underflows
This commit is contained in:
parent
743af38e7f
commit
5406c2b3d3
49
src/load.c
49
src/load.c
@ -8,6 +8,7 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -398,10 +399,11 @@ out:
|
|||||||
free(lex->value.string);
|
free(lex->value.string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lex_scan_number(lex_t *lex, char c, json_error_t *error)
|
static int lex_scan_number(lex_t *lex, char c, json_error_t *error)
|
||||||
{
|
{
|
||||||
const char *saved_text;
|
const char *saved_text;
|
||||||
char *end;
|
char *end;
|
||||||
|
double value;
|
||||||
|
|
||||||
lex->token = TOKEN_INVALID;
|
lex->token = TOKEN_INVALID;
|
||||||
|
|
||||||
@ -422,14 +424,26 @@ static void lex_scan_number(lex_t *lex, char c, json_error_t *error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(c != '.' && c != 'E' && c != 'e') {
|
if(c != '.' && c != 'E' && c != 'e') {
|
||||||
|
long value;
|
||||||
|
|
||||||
lex_unget_unsave(lex, c);
|
lex_unget_unsave(lex, c);
|
||||||
lex->token = TOKEN_INTEGER;
|
|
||||||
|
|
||||||
saved_text = strbuffer_value(&lex->saved_text);
|
saved_text = strbuffer_value(&lex->saved_text);
|
||||||
lex->value.integer = strtol(saved_text, &end, 10);
|
value = strtol(saved_text, &end, 10);
|
||||||
assert(end == saved_text + lex->saved_text.length);
|
assert(end == saved_text + lex->saved_text.length);
|
||||||
|
|
||||||
return;
|
if((value == LONG_MAX && errno == ERANGE) || value > INT_MAX) {
|
||||||
|
error_set(error, lex, "too big integer");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
else if((value == LONG_MIN && errno == ERANGE) || value < INT_MIN) {
|
||||||
|
error_set(error, lex, "too big negative integer");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lex->token = TOKEN_INTEGER;
|
||||||
|
lex->value.integer = (int)value;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(c == '.') {
|
if(c == '.') {
|
||||||
@ -459,14 +473,29 @@ static void lex_scan_number(lex_t *lex, char c, json_error_t *error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
lex_unget_unsave(lex, c);
|
lex_unget_unsave(lex, c);
|
||||||
lex->token = TOKEN_REAL;
|
|
||||||
|
|
||||||
saved_text = strbuffer_value(&lex->saved_text);
|
saved_text = strbuffer_value(&lex->saved_text);
|
||||||
lex->value.real = strtod(saved_text, &end);
|
value = strtod(saved_text, &end);
|
||||||
assert(end == saved_text + lex->saved_text.length);
|
assert(end == saved_text + lex->saved_text.length);
|
||||||
|
|
||||||
|
if(value == 0 && errno == ERANGE) {
|
||||||
|
error_set(error, lex, "real number underflow");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cannot test for +/-HUGE_VAL because the HUGE_VAL constant is
|
||||||
|
only defined in C99 mode. So let's trust in sole errno. */
|
||||||
|
else if(errno == ERANGE) {
|
||||||
|
error_set(error, lex, "real number overflow");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
lex->token = TOKEN_REAL;
|
||||||
|
lex->value.real = value;
|
||||||
|
return 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lex_scan(lex_t *lex, json_error_t *error)
|
static int lex_scan(lex_t *lex, json_error_t *error)
|
||||||
@ -505,8 +534,10 @@ static int lex_scan(lex_t *lex, json_error_t *error)
|
|||||||
else if(c == '"')
|
else if(c == '"')
|
||||||
lex_scan_string(lex, error);
|
lex_scan_string(lex, error);
|
||||||
|
|
||||||
else if(isdigit(c) || c == '-')
|
else if(isdigit(c) || c == '-') {
|
||||||
lex_scan_number(lex, c, error);
|
if(lex_scan_number(lex, c, error))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
else if(isupper(c) || islower(c)) {
|
else if(isupper(c) || islower(c)) {
|
||||||
/* eat up the whole identifier for clearer error messages */
|
/* eat up the whole identifier for clearer error messages */
|
||||||
|
25
test/testdata/invalid
vendored
25
test/testdata/invalid
vendored
@ -127,6 +127,21 @@ invalid token near '1e'
|
|||||||
====
|
====
|
||||||
1
|
1
|
||||||
invalid token near '1e'
|
invalid token near '1e'
|
||||||
|
==== real-positive-overflow ====
|
||||||
|
[123123e100000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number overflow near '123123e100000'
|
||||||
|
==== real-negative-overflow ====
|
||||||
|
[-123123e100000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number overflow near '-123123e100000'
|
||||||
|
==== real-underflow ====
|
||||||
|
[123e-10000000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number underflow near '123e-10000000'
|
||||||
==== integer-starting-with-zero ====
|
==== integer-starting-with-zero ====
|
||||||
[012]
|
[012]
|
||||||
====
|
====
|
||||||
@ -137,6 +152,16 @@ invalid token near '0'
|
|||||||
====
|
====
|
||||||
1
|
1
|
||||||
invalid token near '-0'
|
invalid token near '-0'
|
||||||
|
==== too-big-positive-integer ====
|
||||||
|
[123123123123123]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
too big integer near '123123123123123'
|
||||||
|
==== too-big-negative-integer ====
|
||||||
|
[-123123123123123]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
too big negative integer near '-123123123123123'
|
||||||
==== invalid-identifier ====
|
==== invalid-identifier ====
|
||||||
[troo
|
[troo
|
||||||
====
|
====
|
||||||
|
25
test/testdata/invalid-strip
vendored
25
test/testdata/invalid-strip
vendored
@ -127,6 +127,21 @@ invalid token near '1e'
|
|||||||
====
|
====
|
||||||
1
|
1
|
||||||
invalid token near '1e'
|
invalid token near '1e'
|
||||||
|
==== real-positive-overflow ====
|
||||||
|
[123123e100000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number overflow near '123123e100000'
|
||||||
|
==== real-negative-overflow ====
|
||||||
|
[-123123e100000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number overflow near '-123123e100000'
|
||||||
|
==== real-underflow ====
|
||||||
|
[123e-10000000]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
real number underflow near '123e-10000000'
|
||||||
==== integer-starting-with-zero ====
|
==== integer-starting-with-zero ====
|
||||||
[012]
|
[012]
|
||||||
====
|
====
|
||||||
@ -137,6 +152,16 @@ invalid token near '0'
|
|||||||
====
|
====
|
||||||
1
|
1
|
||||||
invalid token near '-0'
|
invalid token near '-0'
|
||||||
|
==== too-big-positive-integer ====
|
||||||
|
[123123123123123]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
too big integer near '123123123123123'
|
||||||
|
==== too-big-negative-integer ====
|
||||||
|
[-123123123123123]
|
||||||
|
====
|
||||||
|
1
|
||||||
|
too big negative integer near '-123123123123123'
|
||||||
==== invalid-identifier ====
|
==== invalid-identifier ====
|
||||||
[troo
|
[troo
|
||||||
====
|
====
|
||||||
|
Loading…
Reference in New Issue
Block a user