]> git.eshelyaron.com Git - emacs.git/commitdiff
Reject filenames containing NUL bytes.
authorPhilipp Stephani <phst@google.com>
Wed, 23 Dec 2020 11:00:46 +0000 (12:00 +0100)
committerPhilipp Stephani <phst@google.com>
Wed, 23 Dec 2020 11:00:46 +0000 (12:00 +0100)
Such filenames are dangerous, as Emacs would silently only use the
part up to the first NUL byte.  Reject them explicitly instead.

* src/coding.c (encode_file_name_1): New helper function.
(encode_file_name): Check that encoded filename doesn't contain a
NUL byte.
(syms_of_coding): Define 'filenamep' symbol.

* test/src/fileio-tests.el (fileio-tests/null-character): New unit
test.

* etc/NEWS: Document change.

etc/NEWS
src/coding.c
test/src/fileio-tests.el

index 92493b70a0c8f2de968ac214d291ad2ba8db12c2..dee0a37727b075f6f0758806e673300eeb7f6945 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2212,6 +2212,10 @@ presented to users or passed on to other applications.
 ** 'start-process-shell-command' and 'start-file-process-shell-command'
 do not support the old calling conventions any longer.
 
+** Functions operating on local filenames now check that the filenames
+don't contain any NUL bytes.  This avoids subtle bugs caused by
+silently using only the part of the filename until the first NUL byte.
+
 \f
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
index 1afa4aa47495a2d2b285da0c49e116a92c409aec..8c2443889d4673e5d723b35dd1752317a1aefbfa 100644 (file)
@@ -10354,8 +10354,8 @@ decode_file_name (Lisp_Object fname)
 #endif
 }
 
-Lisp_Object
-encode_file_name (Lisp_Object fname)
+static Lisp_Object
+encode_file_name_1 (Lisp_Object fname)
 {
   /* This is especially important during bootstrap and dumping, when
      file-name encoding is not yet known, and therefore any non-ASCII
@@ -10380,6 +10380,19 @@ encode_file_name (Lisp_Object fname)
 #endif
 }
 
+Lisp_Object
+encode_file_name (Lisp_Object fname)
+{
+  Lisp_Object encoded = encode_file_name_1 (fname);
+  /* No system accepts NUL bytes in filenames.  Allowing them can
+     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);
+  return encoded;
+}
+
 DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string,
        2, 4, 0,
        doc: /* Decode STRING which is encoded in CODING-SYSTEM, and return the result.
@@ -11780,6 +11793,7 @@ syms_of_coding (void)
   DEFSYM (Qignored, "ignored");
 
   DEFSYM (Qutf_8_string_p, "utf-8-string-p");
+  DEFSYM (Qfilenamep, "filenamep");
 
   defsubr (&Scoding_system_p);
   defsubr (&Sread_coding_system);
index ed381d151eeab8c3ac00de252fa6f71567d1a14f..8d46abf342a1ba228f4a33ead77c45e454c1a4c4 100644 (file)
@@ -155,3 +155,9 @@ Also check that an encoding error can appear in a symlink."
     (write-region "hello\n" nil f nil 'silent)
     (should-error (insert-file-contents f) :type 'circular-list)
     (delete-file f)))
+
+(ert-deftest fileio-tests/null-character ()
+  (should-error (file-exists-p "/foo\0bar")
+                :type 'wrong-type-argument))
+
+;;; fileio-tests.el ends here