diff --git a/ChangeLog b/ChangeLog index 341ca9302..2deeab256 100644 --- a/ChangeLog +++ b/ChangeLog @@ -408,7 +408,7 @@ * src/system.c (Scm_SysExec), src/libsys.scm (%sys-escape-windows-command-line): When a BAT file - is run via CreateProcess, Windoes uses different rules to parse + is run via CreateProcess, Windows uses different rules to parse the command line, causing a security risk. We reject 'unsafe' characters in the command line arguments if BAT file is the program to run. See CVE-2024-3566 diff --git a/lib/gauche/sysutil.scm b/lib/gauche/sysutil.scm index 17a3346a2..2960d292c 100644 --- a/lib/gauche/sysutil.scm +++ b/lib/gauche/sysutil.scm @@ -114,6 +114,12 @@ ;; This is a generalization of what execvp does to search executable from PATH. ;; This used to be file.util#find-file-in-paths. We moved it here so that ;; sys-exec can rely on it, as we switch to execve(2) from execvp(3). +;; +;; The default value handling of pred and extensions are a bit involved. +;; The default of pred is to check the file is executable, and the default of +;; extensions is '(). However, on Windows, if both are omitted, we default +;; extensions to be '("exe" "com" "cmd" "bad"), to mimic the behaivor of +;; execvp(). (define (sys-find-file name :key (paths (cond [(sys-getenv "PATH") => (cut string-split <> @@ -121,14 +127,27 @@ [gauche.os.windows #\;] [else #\:]))] [else '()])) - (pred (cute sys-access <> X_OK)) - (extensions '())) + pred + extensions) + (define real-predicate + (if (undefined? pred) + (cute sys-access <> X_OK) + pred)) + (define real-extensions + (if (undefined? extensions) + (cond-expand + [gauche.os.windows (if (undefined? pred) + '("exe" "com" "cmd" "bat") + '())] + [else '()]) + (assume-type extensions ( ) + "List of strings expected, but got:" extensions))) (define names - (if (null? extensions) + (if (null? real-extensions) `(,name) (cons name - (map (^e (string-append name "." e)) extensions)))) - (define (try n) (and (pred n) n)) + (map (^e (string-append name "." e)) real-extensions)))) + (define (try n) (and (real-predicate n) n)) (define (abspath? path) ;dupe of file.util#absolute-path? (cond-expand [gauche.os.windows (#/^[\/\\]|^[A-Za-z]:/ path)]