summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2015-12-10 13:43:45 +0800
committerTing-Wei Lan <lantw44@gmail.com>2015-12-10 13:43:45 +0800
commit2bed3000c555d7f7ec33572e7882f1abc86f6660 (patch)
treeb6e38f4a30abedf94003cefef1a1d331e2295293
parent21e4bdf1d0c2772d37672dc7b92b3c924e121968 (diff)
downloadcompiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar.gz
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar.bz2
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar.lz
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar.xz
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.tar.zst
compiler2015-2bed3000c555d7f7ec33572e7882f1abc86f6660.zip
Detect overflows and underflows when scanning numbers
-rw-r--r--src/lexer.l52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/lexer.l b/src/lexer.l
index a947fc1..f7b5550 100644
--- a/src/lexer.l
+++ b/src/lexer.l
@@ -12,6 +12,8 @@
#include "libparser_a-parser.h"
#include <assert.h>
+#include <limits.h>
+#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -82,13 +84,59 @@ ERROR .
return ID;
}
{CONST_INT} {
+ CcmmcState *state = yyextra;
+ int errno_save = errno;
+ errno = 0;
+ long value = strtol(yytext, NULL, 10);
+ if (value > INT_MAX ||
+ (errno == ERANGE && value == LONG_MAX)) {
+ fprintf(stderr, "%zu: error: `%s' overflows\n",
+ state->line_number, yytext);
+ exit(1);
+ }
+ if (value < INT_MIN ||
+ (errno == ERANGE && value == LONG_MIN)) {
+ fprintf(stderr, "%zu: error: `%s' underflows\n",
+ state->line_number, yytext);
+ exit(1);
+ }
+ if (errno != 0) {
+ ERR_DECL;
+ fprintf(stderr, "%zu: error: unexpected interger "
+ "conversion failure: %s\n",
+ state->line_number, ERR_MSG);
+ exit(1);
+ }
yylval->value_const.kind = CCMMC_KIND_CONST_INT;
- yylval->value_const.const_int = atoi(yytext);
+ yylval->value_const.const_int = value;
+ errno = errno_save;
return CONST;
}
{CONST_FLOAT} {
+ CcmmcState *state = yyextra;
+ int errno_save = errno;
+ errno = 0;
+ float value = strtof(yytext, NULL);
+ if (errno == ERANGE && value == HUGE_VAL) {
+ fprintf(stderr, "%zu: error: `%s' overflows\n",
+ state->line_number, yytext);
+ exit(1);
+ }
+ if (errno == ERANGE && value == 0.0) {
+ fprintf(stderr, "%zu: error: `%s' underflows\n",
+ state->line_number, yytext);
+ exit(1);
+ }
+ if (errno != 0) {
+ ERR_DECL;
+ fprintf(stderr, "%zu: error: unexpected floating point "
+ "conversion failure: %s\n",
+ state->line_number, ERR_MSG);
+ exit(1);
+ }
yylval->value_const.kind = CCMMC_KIND_CONST_FLOAT;
- yylval->value_const.const_float = atof(yytext);
+ yylval->value_const.const_float = value;
+ errno = errno_save;
return CONST;
}
{CONST_STRING} {