From 280061ecebcebefc010b3e064c3865b643ed2df6 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Tue, 30 Apr 2024 09:22:41 -0500 Subject: [PATCH] Process chdir option sooner so execFillarg sees it This is a bit hacky due to the way we handle chdir on top of posix_spawn. The logic for making the command line use sh and cd lives in execFillarg, since it must handle the case where the virtual CWD is not the same as the JVM CWD. In order to make sure that processing also happens for incoming chdir: options, this patch pre-processes the options hash just for chdir. Fixes #8126 --- .../java/org/jruby/util/io/PopenExecutor.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/jruby/util/io/PopenExecutor.java b/core/src/main/java/org/jruby/util/io/PopenExecutor.java index 15143f8db43..da4a3c5c580 100644 --- a/core/src/main/java/org/jruby/util/io/PopenExecutor.java +++ b/core/src/main/java/org/jruby/util/io/PopenExecutor.java @@ -87,7 +87,7 @@ public static RubyFixnum spawn(ThreadContext context, IRubyObject[] argv) { ExecArg eargp; IRubyObject fail_str; - eargp = execargNew(context, argv, true, false); + eargp = execargNew(context, argv, context.nil, true, false); execargFixup(context, runtime, eargp); fail_str = eargp.use_shell ? eargp.command_name : eargp.command_name; @@ -110,7 +110,7 @@ public IRubyObject systemInternal(ThreadContext context, IRubyObject[] argv, Str ExecArg eargp; long pid; - eargp = execargNew(context, argv, true, true); + eargp = execargNew(context, argv, context.nil, true, true); execargFixup(context, runtime, eargp); pid = spawnProcess(context, runtime, eargp, errmsg); @@ -297,7 +297,7 @@ public static IRubyObject pipeOpen(ThreadContext context, IRubyObject prog, Stri ExecArg execArg = null; if (!isPopenFork(context.runtime, (RubyString)prog)) - execArg = execargNew(context, argv, true, false); + execArg = execargNew(context, argv, context.nil, true, false); return new PopenExecutor().pipeOpen(context, execArg, modestr, fmode, convconfig); } @@ -340,14 +340,14 @@ public static IRubyObject popen(ThreadContext context, IRubyObject[] argv, RubyC // #endif tmp = ((RubyArray)tmp).aryDup(); // RBASIC_CLEAR_CLASS(tmp); - eargp = execargNew(context, ((RubyArray)tmp).toJavaArray(), false, false); + eargp = execargNew(context, ((RubyArray)tmp).toJavaArray(), opt, false, false); ((RubyArray)tmp).clear(); } else { pname = pname.convertToString(); eargp = null; if (!isPopenFork(runtime, (RubyString)pname)) { IRubyObject[] pname_p = {pname}; - eargp = execargNew(context, pname_p, true, false); + eargp = execargNew(context, pname_p, opt, true, false); pname = pname_p[0]; } } @@ -1678,14 +1678,14 @@ static RubyArray checkExecRedirect1(Ruby runtime, RubyArray ary, IRubyObject key private static final int ST_STOP = 1; // rb_execarg_new - public static ExecArg execargNew(ThreadContext context, IRubyObject[] argv, boolean accept_shell, boolean allow_exc_opt) { + public static ExecArg execargNew(ThreadContext context, IRubyObject[] argv, IRubyObject optForChdir, boolean accept_shell, boolean allow_exc_opt) { ExecArg eargp = new ExecArg(); - execargInit(context, argv, accept_shell, eargp, allow_exc_opt); + execargInit(context, argv, optForChdir, accept_shell, eargp, allow_exc_opt); return eargp; } // rb_execarg_init - private static RubyString execargInit(ThreadContext context, IRubyObject[] argv, boolean accept_shell, ExecArg eargp, boolean allow_exc_opt) { + private static RubyString execargInit(ThreadContext context, IRubyObject[] argv, IRubyObject optForChdir, boolean accept_shell, ExecArg eargp, boolean allow_exc_opt) { RubyString prog, ret; IRubyObject[] env_opt = {context.nil, context.nil}; IRubyObject[][] argv_p = {argv}; @@ -1698,6 +1698,14 @@ private static RubyString execargInit(ThreadContext context, IRubyObject[] argv, optHash = optHash.dupFast(context); exception = optHash.delete(context, exceptionSym); } + + RubySymbol chdirSym = context.runtime.newSymbol("chdir"); + IRubyObject chdir; + if (!optForChdir.isNil() && (chdir = ((RubyHash) optForChdir).delete(chdirSym)) != null) { + eargp.chdirGiven = true; + eargp.chdir_dir = chdir.convertToString().toString(); + } + execFillarg(context, prog, argv_p[0], env_opt[0], env_opt[1], eargp); if (exception.isTrue()) { eargp.exception = true;