mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Do not skip path delimiters after multibyte characters in dln_find on Windows
The dln_find.c object built on its own receives UTF-8 command names from process.c, but scanned them with CharNext in the ANSI code page. With a DBCS code page, a backslash after a multibyte character was missed, and `exec("あ\\foo", "x")` ran `あ\foo` found in PATH instead of the one under the current directory. The copy that win32.c includes keeps using its code page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3e7be38818
commit
10eee53bd5
3 files changed
+20
-5
Notes:
git
2026-09-26 23:26:46 +00:00
No files matched your search
+4
-3
@@ -124,8 +124,9 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
|
||||
return NULL;
|
||||
}
|
||||
#ifdef DOSISH
|
||||
# ifndef CharNext
|
||||
# define CharNext(p) ((p)+1)
|
||||
# ifndef DLN_CHAR_NEXT
|
||||
/* fname is UTF-8 unless win32.c includes this file with its code page */
|
||||
# define DLN_CHAR_NEXT(p) ((p)+1)
|
||||
# endif
|
||||
# ifdef DOSISH_DRIVE_LETTER
|
||||
if ((unsigned char)((p[0] | 0x20) - 'a') < 26u && p[1] == ':') {
|
||||
@@ -151,7 +152,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
|
||||
p++;
|
||||
break;
|
||||
default:
|
||||
p = CharNext(p);
|
||||
p = DLN_CHAR_NEXT(p);
|
||||
}
|
||||
}
|
||||
if (ext) {
|
||||
|
||||
@@ -1166,6 +1166,21 @@ class TestProcess < Test::Unit::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
def test_exec_relative_path_after_multibyte_dir
|
||||
return unless windows?
|
||||
with_tmpchdir {|d|
|
||||
dir = "\u{3042}"
|
||||
Dir.mkdir(dir)
|
||||
File.write("#{dir}/foo.cmd", "@echo cwd\n")
|
||||
Dir.mkdir("path")
|
||||
Dir.mkdir("path/#{dir}")
|
||||
File.write("path/#{dir}/foo.cmd", "@echo path\n")
|
||||
env = {"PATH"=>"#{d}/path;#{ENV["PATH"]}"}
|
||||
r = IO.popen([env, RUBY, "-e", "exec(*ARGV)", "#{dir}\\foo", "x"], &:read)
|
||||
assert_equal("cwd", r.chomp)
|
||||
}
|
||||
end
|
||||
|
||||
def test_system_wordsplit
|
||||
with_tmpchdir {|d|
|
||||
File.write("script", <<-'End')
|
||||
|
||||
+1
-2
@@ -81,8 +81,7 @@ static char *w32_getenv(const char *name, UINT cp);
|
||||
#define DLN_FIND_EXTRA_ARG ,cp
|
||||
#define rb_w32_stati128(path, st) w32_stati128(path, st, cp, FALSE)
|
||||
#define getenv(name) w32_getenv(name, cp) /* Necessarily For dln.c */
|
||||
#undef CharNext
|
||||
#define CharNext(p) CharNextExA(cp, (p), 0)
|
||||
#define DLN_CHAR_NEXT(p) CharNextExA(cp, (p), 0)
|
||||
#define dln_find_exe_r rb_w32_udln_find_exe_r
|
||||
#define dln_find_file_r rb_w32_udln_find_file_r
|
||||
#include "dln.h"
|
||||
|
||||
Reference in new issue
Block a user