From beec203a1db85eab4f139a282160c7978765d3a4 Mon Sep 17 00:00:00 2001 From: nobu Date: Wed, 26 Jan 2011 23:41:47 +0000 Subject: * process.c (proc_exec_v, rb_proc_exec_n, rb_proc_exec) (proc_spawn_n, proc_spawn): get rid of too huge alloca(). [ruby-core:34827], [ruby-core:34833] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30662 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 +++++ process.c | 61 +++++++++++++++++++++++++++++++++-------------- test/ruby/test_process.rb | 9 +++++++ 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7094d5fad..1a143d7e1c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Thu Jan 27 08:41:40 2011 Nobuyoshi Nakada + + * process.c (proc_exec_v, rb_proc_exec_n, rb_proc_exec) + (proc_spawn_n, proc_spawn): get rid of too huge alloca(). + [ruby-core:34827], [ruby-core:34833] + Thu Jan 27 08:32:17 2011 Nobuyoshi Nakada * include/ruby/ruby.h (ALLOCV): new API for exception-safe diff --git a/process.c b/process.c index 2a6a321cb4..2d0dc4466b 100644 --- a/process.c +++ b/process.c @@ -1027,16 +1027,23 @@ exec_with_sh(const char *prog, char **argv) *--argv = (char *)"sh"; execv("/bin/sh", argv); } -#define ALLOCA_ARGV(n) ALLOCA_N(char*, (n)+1) +#define ARGV_COUNT(n) ((n)+1) #else #define try_with_sh(prog, argv) (void)0 -#define ALLOCA_ARGV(n) ALLOCA_N(char*, (n)) +#define ARGV_COUNT(n) (n) #endif +#define ARGV_SIZE(n) (sizeof(char*) * ARGV_COUNT(n)) +#define ALLOC_ARGV(n, v) ALLOCV_N(char*, (v), ARGV_COUNT(n)) +#define ALLOC_ARGV_WITH_STR(n, v, s, l) \ + (char **)(((s) = ALLOCV((v), ARGV_SIZE(n) + (l)) + ARGV_SIZE(n)) - ARGV_SIZE(n)) static int proc_exec_v(char **argv, const char *prog) { char fbuf[MAXPATHLEN]; +#if defined(__EMX__) || defined(OS2) + char **new_argv = NULL; +#endif if (!prog) prog = argv[0]; @@ -1052,16 +1059,15 @@ proc_exec_v(char **argv, const char *prog) char *extension; if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) { - char **new_argv; char *p; int n; for (n = 0; argv[n]; n++) /* no-op */; - new_argv = ALLOCA_N(char*, n + 2); + new_argv = ALLOC_N(char*, n + 2); for (; n > 0; n--) new_argv[n + 1] = argv[n]; - new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]); + new_argv[1] = strcpy(ALLOC_N(char, strlen(argv[0]) + 1), argv[0]); for (p = new_argv[1]; *p != '\0'; p++) if (*p == '/') *p = '\\'; @@ -1078,6 +1084,12 @@ proc_exec_v(char **argv, const char *prog) before_exec(); execv(prog, argv); preserving_errno(try_with_sh(prog, argv); after_exec()); +#if defined(__EMX__) || defined(OS2) + if (new_argv) { + xfree(new_argv[0]); + xfree(new_argv); + } +#endif return -1; } @@ -1086,15 +1098,18 @@ rb_proc_exec_n(int argc, VALUE *argv, const char *prog) { char **args; int i; + int ret = -1; + VALUE v; - args = ALLOCA_ARGV(argc+1); + args = ALLOC_ARGV(argc+1, v); for (i=0; i()~&|\\$;'`\"\n",*s)) { @@ -1234,15 +1258,16 @@ proc_spawn(char *str) return status; } } - a = argv = ALLOCA_ARGV((s - str) / 2 + 2); - s = ALLOCA_N(char, s - str + 1); + a = argv = ALLOC_ARGV_WITH_STR((s - str) / 2 + 2, v, s, s - str + 1); strcpy(s, str); if (*a++ = strtok(s, " \t")) { while (t = strtok(NULL, " \t")) *a++ = t; *a = NULL; } - return argv[0] ? proc_spawn_v(argv, 0) : -1; + status = argv[0] ? proc_spawn_v(argv, 0) : -1; + ALLOCV_END(v); + return status; } #endif #endif diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb index 55bae0650b..b25fa2c0a4 100644 --- a/test/ruby/test_process.rb +++ b/test/ruby/test_process.rb @@ -1231,4 +1231,13 @@ class TestProcess < Test::Unit::TestCase assert_equal("2: a b c\n", result, feature) end end if File.executable?("/bin/sh") + + def test_too_long_path + bug4314 = '[ruby-core:34842]' + assert_raise(Errno::ENOENT, bug4314) {Process.spawn("a" * 100_000_000)} + if /mswin|mingw/ =~ RUBY_PLATFORM + bug4315 = '[ruby-core:34833]' + assert_raise(Errno::ENOENT, bug4315) {Process.spawn('"a"|'*100_000_000)} + end + end end -- cgit v1.2.3