From: Ulya Trofimovich Date: Wed, 29 Jul 2015 13:46:19 +0000 (+0100) Subject: Fixed segfault on options that expect an argument but are passed none. X-Git-Tag: 0.15~168 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c8c8426f1305d3e541c74229a504a32b62f490fe;p=re2c Fixed segfault on options that expect an argument but are passed none. Example of commands that triggered segfault: $ re2c -o $ re2c --type-header $ re2c --input --- diff --git a/re2c/bootstrap/src/conf/parse_opts.cc b/re2c/bootstrap/src/conf/parse_opts.cc index 26ed9fb8..d5852e14 100644 --- a/re2c/bootstrap/src/conf/parse_opts.cc +++ b/re2c/bootstrap/src/conf/parse_opts.cc @@ -1,4 +1,4 @@ -/* Generated by re2c 0.14.3 on Wed Jul 29 12:29:18 2015 */ +/* Generated by re2c 0.14.3 on Wed Jul 29 14:24:46 2015 */ #include #include "src/conf/msg.h" @@ -7,14 +7,14 @@ namespace re2c { -parse_opts_t parse_opts (int argc, char ** argv, Opt & opts) +static inline bool next (char * & arg, char ** & argv) { - if (argc == 1) - { - usage (); - return EXIT_FAIL; - } + arg = *++argv; + return arg != NULL; +} +parse_opts_t parse_opts (char ** argv, Opt & opts) +{ #define YYCTYPE char YYCTYPE * YYCURSOR; YYCTYPE * YYMARKER; @@ -23,8 +23,7 @@ parse_opts_t parse_opts (int argc, char ** argv, Opt & opts) opt: - YYCURSOR = *++argv; - if (YYCURSOR == NULL) + if (!next (YYCURSOR, argv)) { goto end; } @@ -115,7 +114,7 @@ yy13: // all remaining arguments are non-options // so they must be input files // re2c expects exactly one input file - for (const char * f = *++argv; f; f = *++argv) + for (char * f; next (f, argv);) { if (!opts.source (f)) { @@ -442,7 +441,7 @@ yy135: yy137: ++YYCURSOR; if ((yych = *YYCURSOR) <= 0x00) goto yy155; - { *argv = YYCURSOR; goto opt_output; } + { *argv = YYCURSOR; goto opt_output; } yy139: ++YYCURSOR; { opts.reusable (); goto opt_short; } @@ -452,7 +451,7 @@ yy141: yy143: ++YYCURSOR; if ((yych = *YYCURSOR) <= 0x00) goto yy153; - { *argv = YYCURSOR; goto opt_header; } + { *argv = YYCURSOR; goto opt_header; } yy145: ++YYCURSOR; { if (!opts.unicode ()) { error_encoding (); return EXIT_FAIL; } goto opt_short; } @@ -467,10 +466,10 @@ yy151: { if (!opts.utf_16 ()) { error_encoding (); return EXIT_FAIL; } goto opt_short; } yy153: ++YYCURSOR; - { YYCURSOR = *++argv; goto opt_header; } + { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; } yy155: ++YYCURSOR; - { YYCURSOR = *++argv; goto opt_output; } + { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; } } @@ -693,7 +692,7 @@ yy219: yych = *++YYCURSOR; if (yych >= 0x01) goto yy177; ++YYCURSOR; - { YYCURSOR = *++argv; goto opt_header; } + { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; } yy231: yych = *++YYCURSOR; if (yych == 'n') goto yy272; @@ -832,7 +831,7 @@ yy292: yych = *++YYCURSOR; if (yych >= 0x01) goto yy177; ++YYCURSOR; - { YYCURSOR = *++argv; goto opt_output; } + { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; } yy299: yych = *++YYCURSOR; if (yych == '-') goto yy311; @@ -1303,7 +1302,11 @@ yy484: opt_encoding_policy: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--encoding-policy"); + return EXIT_FAIL; + } { YYCTYPE yych; @@ -1381,7 +1384,11 @@ yy513: opt_input: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--input"); + return EXIT_FAIL; + } { YYCTYPE yych; @@ -1438,7 +1445,11 @@ yy533: opt_empty_class: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--empty-class"); + return EXIT_FAIL; + } { YYCTYPE yych; diff --git a/re2c/src/conf/msg.cc b/re2c/src/conf/msg.cc index a69ac459..ca89cce6 100644 --- a/re2c/src/conf/msg.cc +++ b/re2c/src/conf/msg.cc @@ -24,6 +24,11 @@ void error_encoding () error ("only one of switches -e, -w, -x, -u and -8 must be set"); } +void error_arg (const char * option) +{ + error ("expected argument to option %s", option); +} + void warning (const char * type, uint32_t line, bool error, const char * fmt, ...) { static const char * msg = error ? "error" : "warning"; diff --git a/re2c/src/conf/msg.h b/re2c/src/conf/msg.h index 1034131f..f3397d7c 100644 --- a/re2c/src/conf/msg.h +++ b/re2c/src/conf/msg.h @@ -8,6 +8,7 @@ namespace re2c { void error (const char * fmt, ...) RE2C_GXX_ATTRIBUTE ((format (printf, 1, 2))); void error_encoding (); +void error_arg (const char * option); void warning (const char * type, uint32_t line, bool error, const char * fmt, ...) RE2C_GXX_ATTRIBUTE ((format (printf, 4, 5))); void usage (); void vernum (); diff --git a/re2c/src/conf/opt.h b/re2c/src/conf/opt.h index 95409a6e..2c595291 100644 --- a/re2c/src/conf/opt.h +++ b/re2c/src/conf/opt.h @@ -57,7 +57,7 @@ enum parse_opts_t EXIT_FAIL }; -parse_opts_t parse_opts (int argc, char ** argv, Opt & opts); +parse_opts_t parse_opts (char ** argv, Opt & opts); } // namespace re2c diff --git a/re2c/src/conf/parse_opts.re b/re2c/src/conf/parse_opts.re index b3bddb61..b0ab34f0 100644 --- a/re2c/src/conf/parse_opts.re +++ b/re2c/src/conf/parse_opts.re @@ -6,14 +6,14 @@ namespace re2c { -parse_opts_t parse_opts (int argc, char ** argv, Opt & opts) +static inline bool next (char * & arg, char ** & argv) { - if (argc == 1) - { - usage (); - return EXIT_FAIL; - } + arg = *++argv; + return arg != NULL; +} +parse_opts_t parse_opts (char ** argv, Opt & opts) +{ #define YYCTYPE char YYCTYPE * YYCURSOR; YYCTYPE * YYMARKER; @@ -27,8 +27,7 @@ parse_opts_t parse_opts (int argc, char ** argv, Opt & opts) */ opt: - YYCURSOR = *++argv; - if (YYCURSOR == NULL) + if (!next (YYCURSOR, argv)) { goto end; } @@ -44,7 +43,7 @@ opt: // all remaining arguments are non-options // so they must be input files // re2c expects exactly one input file - for (const char * f = *++argv; f; f = *++argv) + for (char * f; next (f, argv);) { if (!opts.source (f)) { @@ -106,10 +105,10 @@ opt_short: "w" { if (!opts.wide_chars ()) { error_encoding (); return EXIT_FAIL; } goto opt_short; } "x" { if (!opts.utf_16 ()) { error_encoding (); return EXIT_FAIL; } goto opt_short; } "8" { if (!opts.utf_8 ()) { error_encoding (); return EXIT_FAIL; } goto opt_short; } - "o" end { YYCURSOR = *++argv; goto opt_output; } - "o" { *argv = YYCURSOR; goto opt_output; } - "t" end { YYCURSOR = *++argv; goto opt_header; } - "t" { *argv = YYCURSOR; goto opt_header; } + "o" end { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; } + "o" { *argv = YYCURSOR; goto opt_output; } + "t" end { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; } + "t" { *argv = YYCURSOR; goto opt_header; } "1" { goto opt_short; } // deprecated */ @@ -142,8 +141,8 @@ opt_long: "wide-chars" end { if (!opts.wide_chars ()) { error_encoding (); return EXIT_FAIL; } goto opt; } "utf-16" end { if (!opts.utf_16 ()) { error_encoding (); return EXIT_FAIL; } goto opt; } "utf-8" end { if (!opts.utf_8 ()) { error_encoding (); return EXIT_FAIL; } goto opt; } - "output" end { YYCURSOR = *++argv; goto opt_output; } - "type-header" end { YYCURSOR = *++argv; goto opt_header; } + "output" end { if (!next (YYCURSOR, argv)) { error_arg ("-o, --output"); return EXIT_FAIL; } goto opt_output; } + "type-header" end { if (!next (YYCURSOR, argv)) { error_arg ("-t, --type-header"); return EXIT_FAIL; } goto opt_header; } "encoding-policy" end { goto opt_encoding_policy; } "input" end { goto opt_input; } "empty-class" end { goto opt_empty_class; } @@ -171,7 +170,11 @@ opt_header: */ opt_encoding_policy: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--encoding-policy"); + return EXIT_FAIL; + } /*!re2c * { @@ -184,7 +187,11 @@ opt_encoding_policy: */ opt_input: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--input"); + return EXIT_FAIL; + } /*!re2c * { @@ -196,7 +203,11 @@ opt_input: */ opt_empty_class: - YYCURSOR = *++argv; + if (!next (YYCURSOR, argv)) + { + error_arg ("--empty-class"); + return EXIT_FAIL; + } /*!re2c * { diff --git a/re2c/src/main.cc b/re2c/src/main.cc index e82803d3..78cbe78f 100644 --- a/re2c/src/main.cc +++ b/re2c/src/main.cc @@ -18,10 +18,10 @@ free_list RegExp::vFreeList; using namespace re2c; -int main(int argc, char *argv[]) +int main(int, char *argv[]) { Opt opts; - switch (parse_opts (argc, argv, opts)) + switch (parse_opts (argv, opts)) { case OK: break; case EXIT_OK: return 0;