diff --git a/src/lua/init.c b/src/lua/init.c index 250b92c15848fc35c9a4942da201945f89b8b870..43395c372e58fb3fecfe69167f3e6996d7efe86d 100644 --- a/src/lua/init.c +++ b/src/lua/init.c @@ -553,7 +553,7 @@ run_script_f(va_list ap) const char *path = va_arg(ap, const char *); bool interactive = va_arg(ap, int); int optc = va_arg(ap, int); - char **optv = va_arg(ap, char **); + const char **optv = va_arg(ap, const char **); int argc = va_arg(ap, int); char **argv = va_arg(ap, char **); /* @@ -656,7 +656,7 @@ run_script_f(va_list ap) int tarantool_lua_run_script(char *path, bool interactive, - int optc, char **optv, int argc, char **argv) + int optc, const char **optv, int argc, char **argv) { const char *title = path ? basename(path) : "interactive"; /* diff --git a/src/lua/init.h b/src/lua/init.h index 507360738f0ac01190e12f4afe7d7ec0f4217646..7fc0b1a319a89df5609e79739d62b048246bc71b 100644 --- a/src/lua/init.h +++ b/src/lua/init.h @@ -72,7 +72,7 @@ tarantool_lua_free(); */ int tarantool_lua_run_script(char *path, bool force_interactive, - int optc, char **optv, + int optc, const char **optv, int argc, char **argv); extern char *history; diff --git a/src/main.cc b/src/main.cc index 4766b0be8a469faa042565f89004d061e50f6e5a..c68ac2af71d4f352bd9058e19f9ce45c009a80ed 100644 --- a/src/main.cc +++ b/src/main.cc @@ -721,7 +721,7 @@ main(int argc, char **argv) bool interactive = false; /* Lua interpeter options, e.g. -e and -l */ int optc = 0; - char **optv = NULL; + const char **optv = NULL; auto guard = make_scoped_guard([=]{ if (optc) free(optv); }); static struct option longopts[] = { @@ -749,16 +749,13 @@ main(int argc, char **argv) case 'e': /* Save Lua interepter options to optv as is */ if (optc == 0) { - optv = (char **) calloc(argc, sizeof(char *)); + optv = (const char **) calloc(argc, + sizeof(optv[0])); if (optv == NULL) panic_syserror("No enough memory for arguments"); } - /* - * The variable optind is the index of the next - * element to be processed in argv. - */ - optv[optc++] = argv[optind - 2]; - optv[optc++] = argv[optind - 1]; + optv[optc++] = ch == 'l' ? "-l" : "-e"; + optv[optc++] = optarg; break; default: /* "invalid option" is printed by getopt */ diff --git a/test/app/gh-4775-crash-args-l-e.result b/test/app/gh-4775-crash-args-l-e.result new file mode 100644 index 0000000000000000000000000000000000000000..88169f700dd93efe54c2d27b852b08517f42e9ca --- /dev/null +++ b/test/app/gh-4775-crash-args-l-e.result @@ -0,0 +1,14 @@ +-- test-run result file version 2 +-- +-- gh-4775: crash on option concatenated with value. +-- +child = io.popen('tarantool -e"print(100) os.exit()"') + | --- + | ... +child:read() + | --- + | - '100' + | ... +-- :close() is omitted, because SIGCHILD may be handled by +-- libev instead of Lua. In that case :close() with fail with +-- ECHILD, but it does not matter for this test. diff --git a/test/app/gh-4775-crash-args-l-e.test.lua b/test/app/gh-4775-crash-args-l-e.test.lua new file mode 100644 index 0000000000000000000000000000000000000000..7dff8e8947dbc05fa11b492f8177434fc94bfc36 --- /dev/null +++ b/test/app/gh-4775-crash-args-l-e.test.lua @@ -0,0 +1,8 @@ +-- +-- gh-4775: crash on option concatenated with value. +-- +child = io.popen('tarantool -e"print(100) os.exit()"') +child:read() +-- :close() is omitted, because SIGCHILD may be handled by +-- libev instead of Lua. In that case :close() with fail with +-- ECHILD, but it does not matter for this test.