From 4e21c5f451a18f96172e63dbe8a3ceef780758bb Mon Sep 17 00:00:00 2001 From: Federico Tedin Date: Wed, 15 Sep 2021 00:15:16 +0200 Subject: [PATCH] Check for null bytes in filenames in 'expand-file-name' (bug#49723) * src/fileio.c (expand-file-name): Check for null bytes for both NAME and DEFAULT-DIRECTORY arguments. Also check for null bytes in buffer-local default-directory, assuming it is used. * src/coding.c (encode_file_name): Use CHECK_STRING_NULL_BYTES. * src/lisp.h (CHECK_STRING_NULL_BYTES): Add function for checking for null bytes in Lisp strings. * test/src/fileio-tests.el (fileio-test--expand-file-name-null-bytes): Add test for new changes to expand-file-name. * etc/NEWS: Announce changes. --- etc/NEWS | 7 +++++++ src/coding.c | 3 +-- src/fileio.c | 6 +++++- src/lisp.h | 7 +++++++ test/src/fileio-tests.el | 9 +++++++++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 515f8bac562..b93e87642b8 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -294,6 +294,13 @@ personalize the uniquified buffer name. --- ** 'remove-hook' is now an interactive command. +** 'expand-file-name' now checks for null bytes in filenames. +The function will now check for null bytes in both NAME and +DEFAULT-DIRECTORY arguments, as well as in the 'default-directory' +buffer-local variable, assuming its value is used. If null bytes are +found, 'expand-file-name' will signal an error. + +--- ** Frames +++ diff --git a/src/coding.c b/src/coding.c index d027c7d5399..7030a53869a 100644 --- a/src/coding.c +++ b/src/coding.c @@ -10430,8 +10430,7 @@ encode_file_name (Lisp_Object fname) cause subtle bugs because the system would silently use a different filename than expected. Perform this check after encoding to not miss NUL bytes introduced through encoding. */ - CHECK_TYPE (memchr (SSDATA (encoded), '\0', SBYTES (encoded)) == NULL, - Qfilenamep, fname); + CHECK_STRING_NULL_BYTES (encoded); return encoded; } diff --git a/src/fileio.c b/src/fileio.c index 0db8ed793b3..3c13d3fe416 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -945,6 +945,7 @@ the root directory. */) USE_SAFE_ALLOCA; CHECK_STRING (name); + CHECK_STRING_NULL_BYTES (name); /* If the file name has special constructs in it, call the corresponding file name handler. */ @@ -993,7 +994,10 @@ the root directory. */) if (STRINGP (dir)) { if (file_name_absolute_no_tilde_p (dir)) - default_directory = dir; + { + CHECK_STRING_NULL_BYTES (dir); + default_directory = dir; + } else { Lisp_Object absdir diff --git a/src/lisp.h b/src/lisp.h index 7bfc69b647b..9716b34baee 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1615,6 +1615,13 @@ STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize) XSTRING (string)->u.s.size = newsize; } +INLINE void +CHECK_STRING_NULL_BYTES (Lisp_Object string) +{ + CHECK_TYPE (memchr (SSDATA (string), '\0', SBYTES (string)) == NULL, + Qfilenamep, string); +} + /* A regular vector is just a header plus an array of Lisp_Objects. */ struct Lisp_Vector diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index f4d123b4261..438ebebb769 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -136,6 +136,15 @@ Also check that an encoding error can appear in a symlink." (should (and (file-name-absolute-p name) (not (eq (aref name 0) ?~)))))) +(ert-deftest fileio-test--expand-file-name-null-bytes () + "Test that expand-file-name checks for null bytes in filenames." + (should-error (expand-file-name (concat "file" (char-to-string ?\0) ".txt")) + :type 'wrong-type-argument) + (should-error (expand-file-name "file.txt" (concat "dir" (char-to-string ?\0))) + :type 'wrong-type-argument) + (let ((default-directory (concat "dir" (char-to-string ?\0)))) + (should-error (expand-file-name "file.txt") :type 'wrong-type-argument))) + (ert-deftest fileio-tests--file-name-absolute-p () "Test file-name-absolute-p." (dolist (suffix '("" "/" "//" "/foo" "/foo/" "/foo//" "/foo/bar")) -- 2.39.5