diff --git a/src/cjules/commands/patch.cr b/src/cjules/commands/patch.cr index 30bfee8..350ae63 100644 --- a/src/cjules/commands/patch.cr +++ b/src/cjules/commands/patch.cr @@ -89,7 +89,7 @@ module Cjules if apply if interactive - unless STDIN.tty? && STDOUT.tty? + unless STDIN.tty? && STDOUT.tty? && STDERR.tty? STDERR.puts "error: --interactive requires a TTY" return 2 end diff --git a/src/cjules/unidiff.cr b/src/cjules/unidiff.cr index a2162a3..5a06911 100644 --- a/src/cjules/unidiff.cr +++ b/src/cjules/unidiff.cr @@ -204,9 +204,12 @@ module Cjules end private def run_editor(editor : String, path : String, output : IO, display : IO) : Bool - # Allow editor commands with flags by going through the shell. - cmd = "#{editor} #{shell_escape(path)}" - status = Process.run("sh", ["-lc", cmd], + # Parse editor command into program + flags and pass path as a separate arg + # to avoid shell injection and quoting issues. + parts = editor.split + program = parts[0] + args = parts[1..] + [path] + status = Process.run(program, args, input: input_for_editor, output: display, error: output) @@ -222,10 +225,6 @@ module Cjules STDIN end - private def shell_escape(s : String) : String - "'" + s.gsub("'", %q('\'')).to_s + "'" - end - private def check_applies?(patch_path : String, output : IO) : Bool out_io = IO::Memory.new err = IO::Memory.new