diff options
author | Ting-Wei Lan <lantw44@gmail.com> | 2015-12-10 13:43:45 +0800 |
---|---|---|
committer | Ting-Wei Lan <lantw44@gmail.com> | 2015-12-10 13:43:45 +0800 |
commit | 2bed3000c555d7f7ec33572e7882f1abc86f6660 (patch) | |
tree | b6e38f4a30abedf94003cefef1a1d331e2295293 | |
parent | 21e4bdf1d0c2772d37672dc7b92b3c924e121968 (diff) | |
download | compiler2015-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.l | 52 |
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} { |