From 819c85733a785084c6e710c47d579260b1c586a1 Mon Sep 17 00:00:00 2001 From: Ulya Trofimovich Date: Sun, 16 Aug 2015 12:08:21 +0100 Subject: [PATCH] Use custom function instead of 'atoi' to read 32-bit integers. Using 'atoi' displeased me for several reasons: - 'atoi' doesn't check for overflow - by the time 'atoi' was called, re2c has already parsed input string and knows that it is well-formed, no need to do it twice - atoi returns 'int', custom function allows to refine types and avoid casts between signed/unsigned values or [-Wsign-conversion] warnings Added test for new conversion functions. --- re2c/Makefile.am | 11 +- re2c/bootstrap/src/parse/scanner_lex.cc | 366 +++++++++++++----------- re2c/src/parse/extop.h | 4 +- re2c/src/parse/parser.ypp | 10 +- re2c/src/parse/scanner_lex.re | 40 ++- re2c/src/test/s_to_n32_unsafe/test.cc | 98 +++++++ re2c/src/util/s_to_n32_unsafe.cc | 53 ++++ re2c/src/util/s_to_n32_unsafe.h | 10 + 8 files changed, 397 insertions(+), 195 deletions(-) create mode 100644 re2c/src/test/s_to_n32_unsafe/test.cc create mode 100644 re2c/src/util/s_to_n32_unsafe.cc create mode 100644 re2c/src/util/s_to_n32_unsafe.h diff --git a/re2c/Makefile.am b/re2c/Makefile.am index b8e77ef3..97769286 100644 --- a/re2c/Makefile.am +++ b/re2c/Makefile.am @@ -63,6 +63,7 @@ SRC_HDR = \ src/util/free_list.h \ src/util/local_increment.h \ src/util/range.h \ + src/util/s_to_n32_unsafe.h \ src/util/smart_ptr.h \ src/util/static_assert.h \ src/util/substr.h \ @@ -113,6 +114,7 @@ SRC = \ src/parse/input.cc \ src/parse/scanner.cc \ src/parse/unescape.cc \ + src/util/s_to_n32_unsafe.cc \ src/util/range.cc re2c_SOURCES = \ $(SRC_HDR) \ @@ -250,6 +252,13 @@ testrange_SOURCES = \ src/util/range.h \ src/util/static_assert.h -check_PROGRAMS = $(TST_RANGE) +TST_S_TO_N32_UNSAFE = testston32unsafe +testston32unsafe_SOURCES = \ + src/test/s_to_n32_unsafe/test.cc \ + src/util/s_to_n32_unsafe.cc + +check_PROGRAMS = \ + $(TST_RANGE) \ + $(TST_S_TO_N32_UNSAFE) TESTS = $(TST_SUITE) $(check_PROGRAMS) diff --git a/re2c/bootstrap/src/parse/scanner_lex.cc b/re2c/bootstrap/src/parse/scanner_lex.cc index 2358193c..612d6597 100644 --- a/re2c/bootstrap/src/parse/scanner_lex.cc +++ b/re2c/bootstrap/src/parse/scanner_lex.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Fri Aug 14 12:58:19 2015 */ +/* Generated by re2c 0.14.3 on Sun Aug 16 11:25:05 2015 */ #line 1 "../src/parse/scanner_lex.re" #include #include @@ -11,13 +11,10 @@ #include "src/parse/parser.h" #include "src/parse/scanner.h" #include "y.tab.h" +#include "src/util/s_to_n32_unsafe.h" extern YYSTYPE yylval; -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - #define YYCTYPE unsigned char #define YYCURSOR cur #define YYLIMIT lim @@ -31,10 +28,10 @@ namespace re2c // source code is in ASCII: pointers have type 'char *' // but re2c makes an implicit assumption that YYCTYPE is unsigned // when it generates comparisons -#line 34 "../src/parse/scanner_lex.re" +#line 31 "../src/parse/scanner_lex.re" -#line 56 "../src/parse/scanner_lex.re" +#line 53 "../src/parse/scanner_lex.re" Scanner::ParseMode Scanner::echo() @@ -50,7 +47,7 @@ Scanner::ParseMode Scanner::echo() tok = cur; echo: -#line 54 "src/parse/scanner_lex.cc" +#line 51 "src/parse/scanner_lex.cc" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -109,7 +106,7 @@ echo: } } ++YYCURSOR; -#line 199 "../src/parse/scanner_lex.re" +#line 196 "../src/parse/scanner_lex.re" { if (!(ignore_eoc || DFlag || flag_skeleton)) { @@ -121,15 +118,15 @@ echo: return Stop; } } -#line 125 "src/parse/scanner_lex.cc" +#line 122 "src/parse/scanner_lex.cc" yy4: ++YYCURSOR; yy5: -#line 210 "../src/parse/scanner_lex.re" +#line 207 "../src/parse/scanner_lex.re" { goto echo; } -#line 133 "src/parse/scanner_lex.cc" +#line 130 "src/parse/scanner_lex.cc" yy6: yyaccept = 0; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); @@ -138,7 +135,7 @@ yy6: } if (yych == '#') goto yy91; yy7: -#line 186 "../src/parse/scanner_lex.re" +#line 183 "../src/parse/scanner_lex.re" { if (ignore_eoc) { @@ -152,7 +149,7 @@ yy7: cline++; goto echo; } -#line 156 "src/parse/scanner_lex.cc" +#line 153 "src/parse/scanner_lex.cc" yy8: yych = (YYCTYPE)*++YYCURSOR; if (yych == '{') goto yy32; @@ -236,7 +233,7 @@ yy21: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 87 "../src/parse/scanner_lex.re" +#line 84 "../src/parse/scanner_lex.re" { if (rFlag) { @@ -249,13 +246,13 @@ yy21: tok = cur; return Rules; } -#line 253 "src/parse/scanner_lex.cc" +#line 250 "src/parse/scanner_lex.cc" yy31: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; yy32: ++YYCURSOR; -#line 72 "../src/parse/scanner_lex.re" +#line 69 "../src/parse/scanner_lex.re" { if (rFlag) { @@ -271,7 +268,7 @@ yy32: tok = cur; return Parse; } -#line 275 "src/parse/scanner_lex.cc" +#line 272 "src/parse/scanner_lex.cc" yy34: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'e') goto yy12; @@ -286,7 +283,7 @@ yy34: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 99 "../src/parse/scanner_lex.re" +#line 96 "../src/parse/scanner_lex.re" { if (!rFlag) { @@ -301,7 +298,7 @@ yy34: tok = cur; return Reuse; } -#line 305 "src/parse/scanner_lex.cc" +#line 302 "src/parse/scanner_lex.cc" yy42: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'x') goto yy12; @@ -316,7 +313,7 @@ yy42: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 113 "../src/parse/scanner_lex.re" +#line 110 "../src/parse/scanner_lex.re" { if (!DFlag) { @@ -326,7 +323,7 @@ yy42: ignore_eoc = true; goto echo; } -#line 330 "src/parse/scanner_lex.cc" +#line 327 "src/parse/scanner_lex.cc" yy50: yych = (YYCTYPE)*++YYCURSOR; if (yych != 't') goto yy12; @@ -351,14 +348,14 @@ yy50: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 122 "../src/parse/scanner_lex.re" +#line 119 "../src/parse/scanner_lex.re" { tok = pos = cur; out.insert_state_goto (topIndent); ignore_eoc = true; goto echo; } -#line 362 "src/parse/scanner_lex.cc" +#line 359 "src/parse/scanner_lex.cc" yy63: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'n') goto yy12; @@ -379,13 +376,13 @@ yy63: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 128 "../src/parse/scanner_lex.re" +#line 125 "../src/parse/scanner_lex.re" { tok = pos = cur; ignore_eoc = true; goto echo; } -#line 389 "src/parse/scanner_lex.cc" +#line 386 "src/parse/scanner_lex.cc" yy74: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'p') goto yy12; @@ -404,7 +401,7 @@ yy74: yych = (YYCTYPE)*++YYCURSOR; if (yych != 'c') goto yy12; ++YYCURSOR; -#line 133 "../src/parse/scanner_lex.re" +#line 130 "../src/parse/scanner_lex.re" { tok = pos = cur; ignore_eoc = true; @@ -418,14 +415,14 @@ yy74: } goto echo; } -#line 422 "src/parse/scanner_lex.cc" +#line 419 "src/parse/scanner_lex.cc" yy84: yyaccept = 2; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); if (yych == '\n') goto yy87; if (yych == '\r') goto yy86; yy85: -#line 164 "../src/parse/scanner_lex.re" +#line 161 "../src/parse/scanner_lex.re" { if (ignore_eoc) { @@ -444,13 +441,13 @@ yy85: tok = pos = cur; goto echo; } -#line 448 "src/parse/scanner_lex.cc" +#line 445 "src/parse/scanner_lex.cc" yy86: yych = (YYCTYPE)*++YYCURSOR; if (yych != '\n') goto yy12; yy87: ++YYCURSOR; -#line 146 "../src/parse/scanner_lex.re" +#line 143 "../src/parse/scanner_lex.re" { cline++; if (ignore_eoc) @@ -469,7 +466,7 @@ yy87: tok = pos = cur; goto echo; } -#line 473 "src/parse/scanner_lex.cc" +#line 470 "src/parse/scanner_lex.cc" yy89: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -544,12 +541,12 @@ yy101: yy103: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 182 "../src/parse/scanner_lex.re" +#line 179 "../src/parse/scanner_lex.re" { set_sourceline (); goto echo; } -#line 553 "src/parse/scanner_lex.cc" +#line 550 "src/parse/scanner_lex.cc" yy105: yych = (YYCTYPE)*++YYCURSOR; if (yych == '\n') goto yy103; @@ -574,7 +571,7 @@ yy109: if (yych == '\r') goto yy105; goto yy12; } -#line 213 "../src/parse/scanner_lex.re" +#line 210 "../src/parse/scanner_lex.re" } @@ -596,7 +593,7 @@ scan: start: -#line 600 "src/parse/scanner_lex.cc" +#line 597 "src/parse/scanner_lex.cc" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -711,22 +708,22 @@ start: yy112: ++YYCURSOR; yy113: -#line 431 "../src/parse/scanner_lex.re" +#line 441 "../src/parse/scanner_lex.re" { fatalf("unexpected character: '%c'", *tok); goto scan; } -#line 720 "src/parse/scanner_lex.cc" +#line 717 "src/parse/scanner_lex.cc" yy114: ++YYCURSOR; yych = (YYCTYPE)*YYCURSOR; goto yy248; yy115: -#line 415 "../src/parse/scanner_lex.re" +#line 425 "../src/parse/scanner_lex.re" { goto scan; } -#line 730 "src/parse/scanner_lex.cc" +#line 727 "src/parse/scanner_lex.cc" yy116: yyaccept = 0; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); @@ -737,14 +734,14 @@ yy116: if (yych == '#') goto yy228; } yy117: -#line 424 "../src/parse/scanner_lex.re" +#line 434 "../src/parse/scanner_lex.re" { if (cur == eof) return 0; pos = cur; cline++; goto scan; } -#line 748 "src/parse/scanner_lex.cc" +#line 745 "src/parse/scanner_lex.cc" yy118: yych = (YYCTYPE)*++YYCURSOR; if (yych == '\n') goto yy225; @@ -754,11 +751,11 @@ yy119: yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); if (yych != '\n') goto yy221; yy120: -#line 289 "../src/parse/scanner_lex.re" +#line 286 "../src/parse/scanner_lex.re" { fatal("unterminated string constant (missing \")"); } -#line 762 "src/parse/scanner_lex.cc" +#line 759 "src/parse/scanner_lex.cc" yy121: yych = (YYCTYPE)*++YYCURSOR; if (yych == '}') goto yy213; @@ -768,44 +765,44 @@ yy122: yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); if (yych != '\n') goto yy216; yy123: -#line 292 "../src/parse/scanner_lex.re" +#line 289 "../src/parse/scanner_lex.re" { fatal("unterminated string constant (missing ')"); } -#line 776 "src/parse/scanner_lex.cc" +#line 773 "src/parse/scanner_lex.cc" yy124: ++YYCURSOR; yy125: -#line 318 "../src/parse/scanner_lex.re" +#line 315 "../src/parse/scanner_lex.re" { return *tok; } -#line 784 "src/parse/scanner_lex.cc" +#line 781 "src/parse/scanner_lex.cc" yy126: ++YYCURSOR; if ((yych = (YYCTYPE)*YYCURSOR) == '/') goto yy213; -#line 322 "../src/parse/scanner_lex.re" +#line 319 "../src/parse/scanner_lex.re" { yylval.op = *tok; return STAR; } -#line 793 "src/parse/scanner_lex.cc" +#line 790 "src/parse/scanner_lex.cc" yy128: ++YYCURSOR; -#line 326 "../src/parse/scanner_lex.re" +#line 323 "../src/parse/scanner_lex.re" { yylval.op = *tok; return CLOSE; } -#line 801 "src/parse/scanner_lex.cc" +#line 798 "src/parse/scanner_lex.cc" yy130: ++YYCURSOR; -#line 410 "../src/parse/scanner_lex.re" +#line 420 "../src/parse/scanner_lex.re" { yylval.regexp = mkDot(); return RANGE; } -#line 809 "src/parse/scanner_lex.cc" +#line 806 "src/parse/scanner_lex.cc" yy132: yych = (YYCTYPE)*++YYCURSOR; if (yych == '*') goto yy209; @@ -833,11 +830,11 @@ yy136: if (yych == '^') goto yy188; goto yy187; yy137: -#line 308 "../src/parse/scanner_lex.re" +#line 305 "../src/parse/scanner_lex.re" { fatal("unterminated range (missing ])"); } -#line 841 "src/parse/scanner_lex.cc" +#line 838 "src/parse/scanner_lex.cc" yy138: YYCTXMARKER = YYCURSOR + 1; yych = (YYCTYPE)*++YYCURSOR; @@ -863,12 +860,12 @@ yy139: } } yy140: -#line 234 "../src/parse/scanner_lex.re" +#line 231 "../src/parse/scanner_lex.re" { depth = 1; goto code; } -#line 872 "src/parse/scanner_lex.cc" +#line 869 "src/parse/scanner_lex.cc" yy141: yych = (YYCTYPE)*++YYCURSOR; if (yych == ',') goto yy160; @@ -940,14 +937,14 @@ yy145: yy147: ++YYCURSOR; yy148: -#line 354 "../src/parse/scanner_lex.re" +#line 364 "../src/parse/scanner_lex.re" { fatal("illegal closure form, use '{n}', '{n,}', '{n,m}' where n and m are numbers"); } -#line 948 "src/parse/scanner_lex.cc" +#line 945 "src/parse/scanner_lex.cc" yy149: ++YYCURSOR; -#line 358 "../src/parse/scanner_lex.re" +#line 368 "../src/parse/scanner_lex.re" { if (!FFlag) { fatal("curly braces for names only allowed with -F switch"); @@ -955,13 +952,16 @@ yy149: yylval.str = new std::string (tok + 1, tok_len () - 2); // -2 to omit braces return ID; } -#line 959 "src/parse/scanner_lex.cc" +#line 956 "src/parse/scanner_lex.cc" yy151: ++YYCURSOR; -#line 336 "../src/parse/scanner_lex.re" +#line 333 "../src/parse/scanner_lex.re" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = atoi((char *)tok+1); + if (!s_to_u32_unsafe (tok + 1, cur - 1, yylval.extop.min)) + { + fatal ("repetition count overflow"); + } + yylval.extop.max = yylval.extop.min; return CLOSESIZE; } #line 968 "src/parse/scanner_lex.cc" @@ -972,13 +972,16 @@ yy153: if (yych <= '9') goto yy156; if (yych != '}') goto yy148; ++YYCURSOR; -#line 348 "../src/parse/scanner_lex.re" +#line 355 "../src/parse/scanner_lex.re" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = -1; + if (!s_to_u32_unsafe (tok + 1, cur - 2, yylval.extop.min)) + { + fatal ("repetition lower bound overflow"); + } + yylval.extop.max = UINT32_MAX; return CLOSESIZE; } -#line 982 "src/parse/scanner_lex.cc" +#line 985 "src/parse/scanner_lex.cc" yy156: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -989,11 +992,18 @@ yy156: ++YYCURSOR; #line 342 "../src/parse/scanner_lex.re" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1)); + const char * p = strchr (tok, ','); + if (!s_to_u32_unsafe (tok + 1, p, yylval.extop.min)) + { + fatal ("repetition lower bound overflow"); + } + if (!s_to_u32_unsafe (p + 1, cur - 1, yylval.extop.max)) + { + fatal ("repetition upper bound overflow"); + } return CLOSESIZE; } -#line 997 "src/parse/scanner_lex.cc" +#line 1007 "src/parse/scanner_lex.cc" yy160: yyaccept = 6; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); @@ -1001,17 +1011,17 @@ yy160: if (yych <= '9') goto yy156; if (yych != '}') goto yy148; ++YYCURSOR; -#line 331 "../src/parse/scanner_lex.re" +#line 328 "../src/parse/scanner_lex.re" { yylval.op = '*'; return CLOSE; } -#line 1010 "src/parse/scanner_lex.cc" +#line 1020 "src/parse/scanner_lex.cc" yy163: ++YYCURSOR; yy164: YYCURSOR = YYCTXMARKER; -#line 391 "../src/parse/scanner_lex.re" +#line 401 "../src/parse/scanner_lex.re" { if (!FFlag) { yylval.str = new std::string (tok, tok_len ()); @@ -1030,7 +1040,7 @@ yy164: return STRING; } } -#line 1034 "src/parse/scanner_lex.cc" +#line 1044 "src/parse/scanner_lex.cc" yy165: yych = (YYCTYPE)*++YYCURSOR; goto yy184; @@ -1038,12 +1048,12 @@ yy166: ++YYCURSOR; yy167: YYCURSOR = YYCTXMARKER; -#line 386 "../src/parse/scanner_lex.re" +#line 396 "../src/parse/scanner_lex.re" { yylval.str = new std::string (tok, tok_len ()); return ID; } -#line 1047 "src/parse/scanner_lex.cc" +#line 1057 "src/parse/scanner_lex.cc" yy168: YYCTXMARKER = YYCURSOR + 1; ++YYCURSOR; @@ -1122,14 +1132,14 @@ yy174: } } yy176: -#line 366 "../src/parse/scanner_lex.re" +#line 376 "../src/parse/scanner_lex.re" { tok += 5; /* skip "re2c:" */ lexer_state = LEX_CONFIG; yylval.str = new std::string (tok, tok_len ()); return CONFIG; } -#line 1133 "src/parse/scanner_lex.cc" +#line 1143 "src/parse/scanner_lex.cc" yy177: yych = (YYCTYPE)*++YYCURSOR; if (yych <= 'Z') { @@ -1188,7 +1198,7 @@ yy179: yy181: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 373 "../src/parse/scanner_lex.re" +#line 383 "../src/parse/scanner_lex.re" { yylval.str = new std::string (tok, tok_len ()); if (FFlag) @@ -1201,7 +1211,7 @@ yy181: return ID; } } -#line 1205 "src/parse/scanner_lex.cc" +#line 1215 "src/parse/scanner_lex.cc" yy183: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1247,13 +1257,13 @@ yy190: goto yy186; yy191: ++YYCURSOR; -#line 302 "../src/parse/scanner_lex.re" +#line 299 "../src/parse/scanner_lex.re" { SubStr s (tok, tok_len ()); yylval.regexp = ranToRE (s); return RANGE; } -#line 1257 "src/parse/scanner_lex.cc" +#line 1267 "src/parse/scanner_lex.cc" yy193: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1262,20 +1272,20 @@ yy193: goto yy188; yy194: ++YYCURSOR; -#line 296 "../src/parse/scanner_lex.re" +#line 293 "../src/parse/scanner_lex.re" { SubStr s (tok, tok_len ()); yylval.regexp = invToRE (s); return RANGE; } -#line 1272 "src/parse/scanner_lex.cc" +#line 1282 "src/parse/scanner_lex.cc" yy196: ++YYCURSOR; -#line 315 "../src/parse/scanner_lex.re" +#line 312 "../src/parse/scanner_lex.re" { return SETUP; } -#line 1279 "src/parse/scanner_lex.cc" +#line 1289 "src/parse/scanner_lex.cc" yy198: YYCTXMARKER = YYCURSOR + 1; yych = (YYCTYPE)*++YYCURSOR; @@ -1305,11 +1315,11 @@ yy200: yy201: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 312 "../src/parse/scanner_lex.re" +#line 309 "../src/parse/scanner_lex.re" { return NOCOND; } -#line 1313 "src/parse/scanner_lex.cc" +#line 1323 "src/parse/scanner_lex.cc" yy203: yych = (YYCTYPE)*++YYCURSOR; if (yych == '>') goto yy201; @@ -1321,44 +1331,44 @@ yy204: yy205: ++YYCURSOR; if ((yych = (YYCTYPE)*YYCURSOR) == '>') goto yy207; -#line 243 "../src/parse/scanner_lex.re" +#line 240 "../src/parse/scanner_lex.re" { tok += 2; /* skip ":=" */ depth = 0; goto code; } -#line 1331 "src/parse/scanner_lex.cc" +#line 1341 "src/parse/scanner_lex.cc" yy207: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 239 "../src/parse/scanner_lex.re" +#line 236 "../src/parse/scanner_lex.re" { return *tok; } -#line 1339 "src/parse/scanner_lex.cc" +#line 1349 "src/parse/scanner_lex.cc" yy209: ++YYCURSOR; -#line 252 "../src/parse/scanner_lex.re" +#line 249 "../src/parse/scanner_lex.re" { depth = 1; goto comment; } -#line 1347 "src/parse/scanner_lex.cc" +#line 1357 "src/parse/scanner_lex.cc" yy211: ++YYCURSOR; -#line 249 "../src/parse/scanner_lex.re" +#line 246 "../src/parse/scanner_lex.re" { goto nextLine; } -#line 1354 "src/parse/scanner_lex.cc" +#line 1364 "src/parse/scanner_lex.cc" yy213: ++YYCURSOR; -#line 258 "../src/parse/scanner_lex.re" +#line 255 "../src/parse/scanner_lex.re" { tok = cur; return 0; } -#line 1362 "src/parse/scanner_lex.cc" +#line 1372 "src/parse/scanner_lex.cc" yy215: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1376,7 +1386,7 @@ yy216: goto yy215; yy218: ++YYCURSOR; -#line 276 "../src/parse/scanner_lex.re" +#line 273 "../src/parse/scanner_lex.re" { SubStr s (tok + 1, tok_len () - 2); // -2 to omit quotes if (bCaseInverted) @@ -1389,7 +1399,7 @@ yy218: } return STRING; } -#line 1393 "src/parse/scanner_lex.cc" +#line 1403 "src/parse/scanner_lex.cc" yy220: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1407,7 +1417,7 @@ yy221: goto yy220; yy223: ++YYCURSOR; -#line 263 "../src/parse/scanner_lex.re" +#line 260 "../src/parse/scanner_lex.re" { SubStr s (tok + 1, tok_len () - 2); // -2 to omit quotes if (bCaseInsensitive || bCaseInverted) @@ -1420,7 +1430,7 @@ yy223: } return STRING; } -#line 1424 "src/parse/scanner_lex.cc" +#line 1434 "src/parse/scanner_lex.cc" yy225: yyaccept = 0; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); @@ -1513,12 +1523,12 @@ yy238: yy240: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 419 "../src/parse/scanner_lex.re" +#line 429 "../src/parse/scanner_lex.re" { set_sourceline (); goto scan; } -#line 1522 "src/parse/scanner_lex.cc" +#line 1532 "src/parse/scanner_lex.cc" yy242: yych = (YYCTYPE)*++YYCURSOR; if (yych == '\n') goto yy240; @@ -1553,12 +1563,12 @@ yy248: if (yych == ' ') goto yy247; goto yy115; } -#line 435 "../src/parse/scanner_lex.re" +#line 445 "../src/parse/scanner_lex.re" flex_name: -#line 1562 "src/parse/scanner_lex.cc" +#line 1572 "src/parse/scanner_lex.cc" { YYCTYPE yych; if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2); @@ -1567,22 +1577,22 @@ flex_name: if (yych == '\r') goto yy255; ++YYCURSOR; yy252: -#line 446 "../src/parse/scanner_lex.re" +#line 456 "../src/parse/scanner_lex.re" { YYCURSOR = tok; goto start; } -#line 1576 "src/parse/scanner_lex.cc" +#line 1586 "src/parse/scanner_lex.cc" yy253: ++YYCURSOR; yy254: -#line 440 "../src/parse/scanner_lex.re" +#line 450 "../src/parse/scanner_lex.re" { YYCURSOR = tok; lexer_state = LEX_NORMAL; return FID_END; } -#line 1586 "src/parse/scanner_lex.cc" +#line 1596 "src/parse/scanner_lex.cc" yy255: yych = (YYCTYPE)*++YYCURSOR; if (yych != '\n') goto yy252; @@ -1590,12 +1600,12 @@ yy255: yych = (YYCTYPE)*YYCURSOR; goto yy254; } -#line 450 "../src/parse/scanner_lex.re" +#line 460 "../src/parse/scanner_lex.re" code: -#line 1599 "src/parse/scanner_lex.cc" +#line 1609 "src/parse/scanner_lex.cc" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1656,7 +1666,7 @@ code: } yy259: ++YYCURSOR; -#line 513 "../src/parse/scanner_lex.re" +#line 523 "../src/parse/scanner_lex.re" { if (cur == eof) { @@ -1668,15 +1678,15 @@ yy259: } goto code; } -#line 1672 "src/parse/scanner_lex.cc" +#line 1682 "src/parse/scanner_lex.cc" yy261: ++YYCURSOR; yy262: -#line 527 "../src/parse/scanner_lex.re" +#line 537 "../src/parse/scanner_lex.re" { goto code; } -#line 1680 "src/parse/scanner_lex.cc" +#line 1690 "src/parse/scanner_lex.cc" yy263: YYCTXMARKER = YYCURSOR + 1; yyaccept = 0; @@ -1696,7 +1706,7 @@ yy263: } } yy264: -#line 494 "../src/parse/scanner_lex.re" +#line 504 "../src/parse/scanner_lex.re" { if (depth == 0) { @@ -1716,7 +1726,7 @@ yy264: cline++; goto code; } -#line 1720 "src/parse/scanner_lex.cc" +#line 1730 "src/parse/scanner_lex.cc" yy265: yyaccept = 1; yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); @@ -1729,7 +1739,7 @@ yy266: goto yy272; yy267: ++YYCURSOR; -#line 466 "../src/parse/scanner_lex.re" +#line 476 "../src/parse/scanner_lex.re" { if (depth == 0) { @@ -1741,10 +1751,10 @@ yy267: } goto code; } -#line 1745 "src/parse/scanner_lex.cc" +#line 1755 "src/parse/scanner_lex.cc" yy269: ++YYCURSOR; -#line 454 "../src/parse/scanner_lex.re" +#line 464 "../src/parse/scanner_lex.re" { if (depth == 0) { @@ -1757,7 +1767,7 @@ yy269: } goto code; } -#line 1761 "src/parse/scanner_lex.cc" +#line 1771 "src/parse/scanner_lex.cc" yy271: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1788,11 +1798,11 @@ yy274: goto yy271; yy275: ++YYCURSOR; -#line 524 "../src/parse/scanner_lex.re" +#line 534 "../src/parse/scanner_lex.re" { goto code; } -#line 1796 "src/parse/scanner_lex.cc" +#line 1806 "src/parse/scanner_lex.cc" yy277: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -1819,7 +1829,7 @@ yy280: } yy281: YYCURSOR = YYCTXMARKER; -#line 481 "../src/parse/scanner_lex.re" +#line 491 "../src/parse/scanner_lex.re" { if (depth == 0) { @@ -1833,7 +1843,7 @@ yy281: cline++; goto code; } -#line 1837 "src/parse/scanner_lex.cc" +#line 1847 "src/parse/scanner_lex.cc" yy282: yych = (YYCTYPE)*++YYCURSOR; goto yy281; @@ -1900,12 +1910,12 @@ yy293: yy295: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 477 "../src/parse/scanner_lex.re" +#line 487 "../src/parse/scanner_lex.re" { set_sourceline (); goto code; } -#line 1909 "src/parse/scanner_lex.cc" +#line 1919 "src/parse/scanner_lex.cc" yy297: yych = (YYCTYPE)*++YYCURSOR; if (yych == '\n') goto yy295; @@ -1944,12 +1954,12 @@ yy302: goto yy273; } } -#line 530 "../src/parse/scanner_lex.re" +#line 540 "../src/parse/scanner_lex.re" comment: -#line 1953 "src/parse/scanner_lex.cc" +#line 1963 "src/parse/scanner_lex.cc" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -1996,7 +2006,7 @@ comment: } ++YYCURSOR; yy307: -#line 562 "../src/parse/scanner_lex.re" +#line 572 "../src/parse/scanner_lex.re" { if (cur == eof) { @@ -2004,7 +2014,7 @@ yy307: } goto comment; } -#line 2008 "src/parse/scanner_lex.cc" +#line 2018 "src/parse/scanner_lex.cc" yy308: yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); if (yybm[0+yych] & 32) { @@ -2012,7 +2022,7 @@ yy308: } if (yych == '#') goto yy319; yy309: -#line 553 "../src/parse/scanner_lex.re" +#line 563 "../src/parse/scanner_lex.re" { if (cur == eof) { @@ -2022,7 +2032,7 @@ yy309: cline++; goto comment; } -#line 2026 "src/parse/scanner_lex.cc" +#line 2036 "src/parse/scanner_lex.cc" yy310: yych = (YYCTYPE)*++YYCURSOR; if (yych == '/') goto yy314; @@ -2031,16 +2041,16 @@ yy311: yych = (YYCTYPE)*++YYCURSOR; if (yych != '*') goto yy307; ++YYCURSOR; -#line 544 "../src/parse/scanner_lex.re" +#line 554 "../src/parse/scanner_lex.re" { ++depth; fatal("ambiguous /* found"); goto comment; } -#line 2041 "src/parse/scanner_lex.cc" +#line 2051 "src/parse/scanner_lex.cc" yy314: ++YYCURSOR; -#line 534 "../src/parse/scanner_lex.re" +#line 544 "../src/parse/scanner_lex.re" { if (--depth == 0) { @@ -2051,7 +2061,7 @@ yy314: goto comment; } } -#line 2055 "src/parse/scanner_lex.cc" +#line 2065 "src/parse/scanner_lex.cc" yy316: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -2129,12 +2139,12 @@ yy329: yy331: ++YYCURSOR; YYCURSOR = YYCTXMARKER; -#line 549 "../src/parse/scanner_lex.re" +#line 559 "../src/parse/scanner_lex.re" { set_sourceline (); goto comment; } -#line 2138 "src/parse/scanner_lex.cc" +#line 2148 "src/parse/scanner_lex.cc" yy333: yych = (YYCTYPE)*++YYCURSOR; if (yych == '\n') goto yy331; @@ -2159,28 +2169,28 @@ yy337: if (yych == '\r') goto yy333; goto yy318; } -#line 569 "../src/parse/scanner_lex.re" +#line 579 "../src/parse/scanner_lex.re" nextLine: -#line 2168 "src/parse/scanner_lex.cc" +#line 2178 "src/parse/scanner_lex.cc" { YYCTYPE yych; if (YYLIMIT <= YYCURSOR) YYFILL(1); yych = (YYCTYPE)*YYCURSOR; if (yych == '\n') goto yy342; ++YYCURSOR; -#line 580 "../src/parse/scanner_lex.re" +#line 590 "../src/parse/scanner_lex.re" { if(cur == eof) { return 0; } goto nextLine; } -#line 2181 "src/parse/scanner_lex.cc" +#line 2191 "src/parse/scanner_lex.cc" yy342: ++YYCURSOR; -#line 573 "../src/parse/scanner_lex.re" +#line 583 "../src/parse/scanner_lex.re" { if(cur == eof) { return 0; } @@ -2188,14 +2198,14 @@ yy342: cline++; goto scan; } -#line 2192 "src/parse/scanner_lex.cc" +#line 2202 "src/parse/scanner_lex.cc" } -#line 585 "../src/parse/scanner_lex.re" +#line 595 "../src/parse/scanner_lex.re" config: -#line 2199 "src/parse/scanner_lex.cc" +#line 2209 "src/parse/scanner_lex.cc" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -2241,32 +2251,32 @@ config: if (yych == '=') goto yy350; } ++YYCURSOR; -#line 596 "../src/parse/scanner_lex.re" +#line 606 "../src/parse/scanner_lex.re" { fatal("missing '='"); } -#line 2249 "src/parse/scanner_lex.cc" +#line 2259 "src/parse/scanner_lex.cc" yy348: ++YYCURSOR; yych = (YYCTYPE)*YYCURSOR; goto yy355; yy349: -#line 589 "../src/parse/scanner_lex.re" +#line 599 "../src/parse/scanner_lex.re" { goto config; } -#line 2259 "src/parse/scanner_lex.cc" +#line 2269 "src/parse/scanner_lex.cc" yy350: ++YYCURSOR; yych = (YYCTYPE)*YYCURSOR; goto yy353; yy351: -#line 592 "../src/parse/scanner_lex.re" +#line 602 "../src/parse/scanner_lex.re" { lexer_state = LEX_CONFIG_VALUE; return '='; } -#line 2270 "src/parse/scanner_lex.cc" +#line 2280 "src/parse/scanner_lex.cc" yy352: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -2285,12 +2295,12 @@ yy355: if (yych == ' ') goto yy354; goto yy349; } -#line 599 "../src/parse/scanner_lex.re" +#line 609 "../src/parse/scanner_lex.re" value: -#line 2294 "src/parse/scanner_lex.cc" +#line 2304 "src/parse/scanner_lex.cc" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -2357,26 +2367,29 @@ value: } } yy358: -#line 608 "../src/parse/scanner_lex.re" +#line 621 "../src/parse/scanner_lex.re" { yylval.str = new std::string (tok, tok_len ()); lexer_state = LEX_NORMAL; return VALUE; } -#line 2367 "src/parse/scanner_lex.cc" +#line 2377 "src/parse/scanner_lex.cc" yy359: ++YYCURSOR; if (yybm[0+(yych = (YYCTYPE)*YYCURSOR)] & 8) { goto yy364; } yy360: -#line 603 "../src/parse/scanner_lex.re" +#line 613 "../src/parse/scanner_lex.re" { - yylval.number = atoi(std::string (tok, tok_len ()).c_str()); + if (!s_to_i32_unsafe (tok, cur, yylval.number)) + { + fatal ("configuration value overflow"); + } lexer_state = LEX_NORMAL; return NUMBER; } -#line 2380 "src/parse/scanner_lex.cc" +#line 2393 "src/parse/scanner_lex.cc" yy361: yych = (YYCTYPE)*++YYCURSOR; if (yych <= '0') goto yy365; @@ -2519,7 +2532,7 @@ yy379: if (yych == '\n') goto yy372; goto yy376; } -#line 613 "../src/parse/scanner_lex.re" +#line 626 "../src/parse/scanner_lex.re" } @@ -2542,7 +2555,7 @@ void Scanner::set_sourceline () sourceline: tok = cur; -#line 2546 "src/parse/scanner_lex.cc" +#line 2559 "src/parse/scanner_lex.cc" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -2591,14 +2604,14 @@ sourceline: yy382: ++YYCURSOR; yy383: -#line 655 "../src/parse/scanner_lex.re" +#line 671 "../src/parse/scanner_lex.re" { goto sourceline; } -#line 2599 "src/parse/scanner_lex.cc" +#line 2612 "src/parse/scanner_lex.cc" yy384: ++YYCURSOR; -#line 643 "../src/parse/scanner_lex.re" +#line 659 "../src/parse/scanner_lex.re" { if (cur == eof) { @@ -2611,7 +2624,7 @@ yy384: tok = cur; return; } -#line 2615 "src/parse/scanner_lex.cc" +#line 2628 "src/parse/scanner_lex.cc" yy386: yych = (YYCTYPE)*(YYMARKER = ++YYCURSOR); if (yych == '\n') goto yy383; @@ -2621,12 +2634,15 @@ yy387: yych = (YYCTYPE)*YYCURSOR; goto yy390; yy388: -#line 635 "../src/parse/scanner_lex.re" +#line 648 "../src/parse/scanner_lex.re" { - cline = atoi(std::string (tok, tok_len ()).c_str()); + if (!s_to_u32_unsafe (tok, cur, cline)) + { + fatal ("line number overflow"); + } goto sourceline; } -#line 2630 "src/parse/scanner_lex.cc" +#line 2646 "src/parse/scanner_lex.cc" yy389: ++YYCURSOR; if (YYLIMIT <= YYCURSOR) YYFILL(1); @@ -2658,14 +2674,14 @@ yy394: goto yy391; yy395: ++YYCURSOR; -#line 639 "../src/parse/scanner_lex.re" +#line 655 "../src/parse/scanner_lex.re" { escape (in.file_name, std::string (tok + 1, tok_len () - 2)); // -2 to omit quotes goto sourceline; } -#line 2667 "src/parse/scanner_lex.cc" +#line 2683 "src/parse/scanner_lex.cc" } -#line 658 "../src/parse/scanner_lex.re" +#line 674 "../src/parse/scanner_lex.re" } diff --git a/re2c/src/parse/extop.h b/re2c/src/parse/extop.h index f2ac5cd0..d093be92 100644 --- a/re2c/src/parse/extop.h +++ b/re2c/src/parse/extop.h @@ -8,8 +8,8 @@ namespace re2c struct ExtOp { - int32_t minsize; - int32_t maxsize; + uint32_t min; + uint32_t max; }; } // end namespace re2c diff --git a/re2c/src/parse/parser.ypp b/re2c/src/parse/parser.ypp index 1c9ae042..fba9a9f5 100644 --- a/re2c/src/parse/parser.ypp +++ b/re2c/src/parse/parser.ypp @@ -420,17 +420,17 @@ factor: | primary CLOSESIZE { $1->ins_access = RegExp::PRIVATE; - if ($2.maxsize < 0) + if ($2.max == UINT32_MAX) { - $$ = repeat_from ($1, $2.minsize); + $$ = repeat_from ($1, $2.min); } - else if ($2.minsize == $2.maxsize) + else if ($2.min == $2.max) { - $$ = repeat ($1, $2.minsize); + $$ = repeat ($1, $2.min); } else { - $$ = repeat_from_to ($1, $2.minsize, $2.maxsize); + $$ = repeat_from_to ($1, $2.min, $2.max); } $$ = $$ ? $$ : new NullOp; } diff --git a/re2c/src/parse/scanner_lex.re b/re2c/src/parse/scanner_lex.re index 9b8eaa3f..91bb7bba 100644 --- a/re2c/src/parse/scanner_lex.re +++ b/re2c/src/parse/scanner_lex.re @@ -9,13 +9,10 @@ #include "src/parse/parser.h" #include "src/parse/scanner.h" #include "y.tab.h" +#include "src/util/s_to_n32_unsafe.h" extern YYSTYPE yylval; -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - #define YYCTYPE unsigned char #define YYCURSOR cur #define YYLIMIT lim @@ -334,20 +331,33 @@ start: } "{" [0-9]+ "}" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = atoi((char *)tok+1); + if (!s_to_u32_unsafe (tok + 1, cur - 1, yylval.extop.min)) + { + fatal ("repetition count overflow"); + } + yylval.extop.max = yylval.extop.min; return CLOSESIZE; } "{" [0-9]+ "," [0-9]+ "}" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = MAX(yylval.extop.minsize,atoi(strchr((char *)tok, ',')+1)); + const char * p = strchr (tok, ','); + if (!s_to_u32_unsafe (tok + 1, p, yylval.extop.min)) + { + fatal ("repetition lower bound overflow"); + } + if (!s_to_u32_unsafe (p + 1, cur - 1, yylval.extop.max)) + { + fatal ("repetition upper bound overflow"); + } return CLOSESIZE; } "{" [0-9]+ ",}" { - yylval.extop.minsize = atoi((char *)tok+1); - yylval.extop.maxsize = -1; + if (!s_to_u32_unsafe (tok + 1, cur - 2, yylval.extop.min)) + { + fatal ("repetition lower bound overflow"); + } + yylval.extop.max = UINT32_MAX; return CLOSESIZE; } @@ -601,7 +611,10 @@ config: value: /*!re2c number { - yylval.number = atoi(std::string (tok, tok_len ()).c_str()); + if (!s_to_i32_unsafe (tok, cur, yylval.number)) + { + fatal ("configuration value overflow"); + } lexer_state = LEX_NORMAL; return NUMBER; } @@ -633,7 +646,10 @@ sourceline: tok = cur; /*!re2c lineno { - cline = atoi(std::string (tok, tok_len ()).c_str()); + if (!s_to_u32_unsafe (tok, cur, cline)) + { + fatal ("line number overflow"); + } goto sourceline; } dstring { diff --git a/re2c/src/test/s_to_n32_unsafe/test.cc b/re2c/src/test/s_to_n32_unsafe/test.cc new file mode 100644 index 00000000..44977beb --- /dev/null +++ b/re2c/src/test/s_to_n32_unsafe/test.cc @@ -0,0 +1,98 @@ +#include + +#include "src/util/s_to_n32_unsafe.h" + +namespace re2c_test { + +static const uint32_t DIGITS = 256; + +// writes string backwards and returns pointer to the start +// no terminating null as we don't need it +static char * u64_to_s_fastest_ever (uint64_t u, char * s) +{ + while (u > 0) + { + const uint64_t d = u % 10 + '0'; + *--s = static_cast (d); + u /= 10; + } + return s; +} + +static int32_t test_u (uint64_t i) +{ + char s [DIGITS]; + char * const s_end = s + DIGITS; + char * const s_start = u64_to_s_fastest_ever (i, s_end); + uint32_t u = i == 0; // not equal to i + if (s_to_u32_unsafe (s_start, s_end, u) && u != i) + { + fprintf (stderr, "unsigned: expected: %lu, got: %u\n", i, u); + return 1; + } + return 0; +} + +static int32_t test_i (int64_t i) +{ + char s [DIGITS]; + char * const s_end = s + DIGITS; + const uint64_t i_abs = i < 0 + ? static_cast (-i) + : static_cast (i); + char * s_start = u64_to_s_fastest_ever (i_abs, s_end); + if (i < 0) + { + *--s_start = '-'; + } + int32_t j = i == 0; // not equal to i + if (s_to_i32_unsafe (s_start, s_end, j) && j != i) + { + fprintf (stderr, "signed: expected: %ld, got: %d\n", i, j); + return 1; + } + return 0; +} + +static int32_t test () +{ + int32_t ok = 0; + + static const uint64_t UDELTA = 0xFFFF; + // zero neighbourhood + for (uint64_t i = 0; i <= UDELTA; ++i) + { + ok |= test_u (i); + } + // UINT32_MAX neighbourhood + for (uint64_t i = UINT32_MAX - UDELTA; i <= UINT32_MAX + UDELTA; ++i) + { + ok |= test_u (i); + } + + static const int64_t IDELTA = 0xFFFF; + // INT32_MIN neighbourhood + for (int64_t i = INT32_MIN - IDELTA; i <= INT32_MIN + IDELTA; ++i) + { + ok |= test_i (i); + } + // zero neighbourhood + for (int64_t i = -IDELTA; i <= IDELTA; ++i) + { + ok |= test_i (i); + } + // INT32_MAX neighbourhood + for (int64_t i = INT32_MAX - IDELTA; i <= INT32_MAX + IDELTA; ++i) + { + ok |= test_i (i); + } + + return ok; +} + +} // namespace re2c_test + +int main () +{ + return re2c_test::test (); +} diff --git a/re2c/src/util/s_to_n32_unsafe.cc b/re2c/src/util/s_to_n32_unsafe.cc new file mode 100644 index 00000000..050547c2 --- /dev/null +++ b/re2c/src/util/s_to_n32_unsafe.cc @@ -0,0 +1,53 @@ +#include "src/util/s_to_n32_unsafe.h" + +// assumes that string matches regexp [0-9]+ +// returns false on overflow +bool s_to_u32_unsafe (const char * s, const char * s_end, uint32_t & number) +{ + uint64_t u = 0; + for (; s != s_end; ++s) + { + u *= 10; + u += static_cast (*s) - 0x30; + if (u >= UINT32_MAX) + { + return false; + } + } + number = static_cast (u); + return true; +} + +// assumes that string matches regexp "-"? [0-9]+ +// returns false on underflow/overflow +bool s_to_i32_unsafe (const char * s, const char * s_end, int32_t & number) +{ + int64_t i = 0; + if (*s == '-') + { + ++s; + for (; s != s_end; ++s) + { + i *= 10; + i -= *s - 0x30; + if (i < INT32_MIN) + { + return false; + } + } + } + else + { + for (; s != s_end; ++s) + { + i *= 10; + i += *s - 0x30; + if (i > INT32_MAX) + { + return false; + } + } + } + number = static_cast (i); + return true; +} diff --git a/re2c/src/util/s_to_n32_unsafe.h b/re2c/src/util/s_to_n32_unsafe.h new file mode 100644 index 00000000..e733c161 --- /dev/null +++ b/re2c/src/util/s_to_n32_unsafe.h @@ -0,0 +1,10 @@ +#ifndef _RE2C_UTIL_S_TO_N32_UNSAFE_ +#define _RE2C_UTIL_S_TO_N32_UNSAFE_ + +#include "src/util/attribute.h" +#include "src/util/c99_stdint.h" + +bool s_to_u32_unsafe (const char * s, const char * s_end, uint32_t & number) RE2C_GXX_ATTRIBUTE ((warn_unused_result)); +bool s_to_i32_unsafe (const char * s, const char * s_end, int32_t & number) RE2C_GXX_ATTRIBUTE ((warn_unused_result)); + +#endif // _RE2C_UTIL_S_TO_N32_UNSAFE_ -- 2.40.0