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:
Hiroshi SHIBATAandClaude Opus 5.5 committed 2026-09-27 08:26:13 +09:00
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
View File
@@ -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) {
+15
View File
@@ -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
View File
@@ -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"