summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hansen <rhansen@rhansen.org>2022-06-09 20:41:50 -0400
committerEli Zaretskii <eliz@gnu.org>2022-06-16 09:55:49 +0300
commit6c3b6149d9e7c882729634dc5a7e647daeecfdf3 (patch)
tree5690c2fcaec05edda7a42d4cbe6edc9fca1b7fe8
parentdcee64d4bf2751a6b67716e2e43267d9e73640cd (diff)
downloademacs-6c3b6149d9e7c882729634dc5a7e647daeecfdf3.tar.gz
bindat (strz): Write null terminator after variable length string
* lisp/emacs-lisp/bindat.el (bindat--pack-strz): Explicitly write a null byte after packing a variable-length string to ensure proper termination when packing to a pre-allocated string. * doc/lispref/processes.texi (Bindat Types): Update documentation. * test/lisp/emacs-lisp/bindat-tests.el (bindat-test--str-strz-prealloc): Update tests.
-rw-r--r--doc/lispref/processes.texi17
-rw-r--r--lisp/emacs-lisp/bindat.el3
-rw-r--r--test/lisp/emacs-lisp/bindat-tests.el4
3 files changed, 9 insertions, 15 deletions
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 8c8f8fd6b2a..179980c0ed7 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -3495,24 +3495,15 @@ output.
@item strz &optional @var{len}
If @var{len} is not provided: Variable-length null-terminated unibyte
string (@pxref{Text Representations}). When packing, the entire input
-string is copied to the packed output. The following byte will be
-null (zero) unless a pre-allocated string was provided to
-@code{bindat-pack}, in which case that byte is left unmodified. The
-length of the packed output is the length of the input string plus one
-(for the null terminator). The input string must not contain any null
-bytes. If the input string is multibyte with only ASCII and
+string is copied to the packed output followed by a null (zero) byte.
+The length of the packed output is the length of the input string plus
+one (for the null terminator). The input string must not contain any
+null bytes. If the input string is multibyte with only ASCII and
@code{eight-bit} characters, it is converted to unibyte before it is
packed; other multibyte strings signal an error. When unpacking, the
resulting string contains all bytes up to (but excluding) the null
byte.
-@quotation Caution
-If a pre-allocated string is provided to @code{bindat-pack}, the
-packed output will not be properly null-terminated unless the
-pre-allocated string already has a null byte at the appropriate
-location.
-@end quotation
-
If @var{len} is provided: @code{strz} behaves the same as @code{str}
with one difference: When unpacking, the first null byte encountered
in the packed string and all subsequent bytes are excluded from the
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 9ba89a5e3fe..46e2a4901c3 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -450,6 +450,9 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
;; need to scan the input string looking for a null byte.
(error "Null byte encountered in input strz string"))
(aset bindat-raw (+ bindat-idx i) (aref v i)))
+ ;; Explicitly write a null terminator in case the user provided a
+ ;; pre-allocated string to bindat-pack that wasn't zeroed first.
+ (aset bindat-raw (+ bindat-idx len) 0)
(setq bindat-idx (+ bindat-idx len 1))))
(defun bindat--pack-bits (len v)
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el
index 7d1233ded7c..cc223ad14e2 100644
--- a/test/lisp/emacs-lisp/bindat-tests.el
+++ b/test/lisp/emacs-lisp/bindat-tests.el
@@ -182,8 +182,8 @@
((((x strz 2)) ((x . "a"))) . "ax")
((((x strz 2)) ((x . "ab"))) . "ab")
((((x strz 2)) ((x . "abc"))) . "ab")
- ((,(bindat-type strz) "") . "xx")
- ((,(bindat-type strz) "a") . "ax")))
+ ((,(bindat-type strz) "") . "\0x")
+ ((,(bindat-type strz) "a") . "a\0")))
(let ((prealloc (make-string 2 ?x)))
(apply #'bindat-pack (append (car tc) (list prealloc)))
(should (equal prealloc (cdr tc))))))