Skip to content

Commit 22754e4

Browse files
lisp: add overflow checks to integer parser
Check that the additions and multiplications don't overflow. In those cases the number is too large to be represented as a tagged value. One day this will cause promotion to heap allocated big integers. For now, exiting unsuccessfully is the only thing lone can possibly do.
1 parent 8e140e1 commit 22754e4

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

source/lone/lisp/value/integer.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,34 @@ struct lone_lisp_value lone_lisp_integer_from_pointer(void *pointer)
2424

2525
struct lone_lisp_value lone_lisp_integer_parse(struct lone_lisp *lone, unsigned char *digits, size_t count)
2626
{
27-
size_t i = 0;
28-
long integer = 0;
27+
size_t i;
28+
long integer, digit;
29+
bool negative;
2930

30-
switch (*digits) { case '+': case '-': ++i; break; }
31+
i = 0;
32+
integer = 0;
33+
negative = false;
3134

32-
while (i < count) {
33-
integer *= 10;
34-
integer += digits[i++] - '0';
35+
switch (*digits) {
36+
case '-':
37+
negative = true;
38+
__attribute__((fallthrough));
39+
case '+':
40+
++i;
41+
break;
3542
}
3643

37-
if (*digits == '-') { integer *= -1; }
44+
while (i < count) {
45+
digit = digits[i++] - '0';
46+
if (negative) { digit = -digit; }
47+
if (__builtin_mul_overflow(integer, 10, &integer)) { goto overflow; }
48+
if (__builtin_add_overflow(integer, digit, &integer)) { goto overflow; }
49+
}
3850

3951
return lone_lisp_integer_create(integer);
52+
53+
overflow:
54+
linux_exit(-1);
4055
}
4156

4257
struct lone_lisp_value lone_lisp_zero(void)

0 commit comments

Comments
 (0)