diff options
| author | Richard Hansen | 2022-06-12 01:19:43 -0400 |
|---|---|---|
| committer | Eli Zaretskii | 2022-06-12 09:59:13 +0300 |
| commit | c1829b307cffce046bec6fcbdff03dbab9f4b562 (patch) | |
| tree | 0814466d82fb9bf840ba719a060f2026931fa643 | |
| parent | c2695621fc52aa5eeebc45b82b9b916e30568589 (diff) | |
| download | emacs-c1829b307cffce046bec6fcbdff03dbab9f4b562.tar.gz emacs-c1829b307cffce046bec6fcbdff03dbab9f4b562.zip | |
bindat (str, strz): Reject non-ASCII, non-`eight-bit' characters
* lisp/emacs-lisp/bindat.el (str) (strz): Signal an error if the user
attempts to pack a multibyte string containing characters other than
ASCII and `eight-bit' characters (bug#55897).
* doc/lispref/processes.texi (Bindat Types): Update documentation.
* test/lisp/emacs-lisp/bindat-tests.el (str) (strz): Add tests.
| -rw-r--r-- | doc/lispref/processes.texi | 14 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bindat.el | 10 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/bindat-tests.el | 16 |
3 files changed, 32 insertions, 8 deletions
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index aa4d0e3ee4f..8c8f8fd6b2a 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi | |||
| @@ -3486,8 +3486,11 @@ When packing, the first @var{len} bytes of the input string are copied | |||
| 3486 | to the packed output. If the input string is shorter than @var{len}, | 3486 | to the packed output. If the input string is shorter than @var{len}, |
| 3487 | the remaining bytes will be null (zero) unless a pre-allocated string | 3487 | the remaining bytes will be null (zero) unless a pre-allocated string |
| 3488 | was provided to @code{bindat-pack}, in which case the remaining bytes | 3488 | was provided to @code{bindat-pack}, in which case the remaining bytes |
| 3489 | are left unmodified. When unpacking, any null bytes in the packed | 3489 | are left unmodified. If the input string is multibyte with only ASCII |
| 3490 | input string will appear in the unpacked output. | 3490 | and @code{eight-bit} characters, it is converted to unibyte before it |
| 3491 | is packed; other multibyte strings signal an error. When unpacking, | ||
| 3492 | any null bytes in the packed input string will appear in the unpacked | ||
| 3493 | output. | ||
| 3491 | 3494 | ||
| 3492 | @item strz &optional @var{len} | 3495 | @item strz &optional @var{len} |
| 3493 | If @var{len} is not provided: Variable-length null-terminated unibyte | 3496 | If @var{len} is not provided: Variable-length null-terminated unibyte |
| @@ -3497,8 +3500,11 @@ null (zero) unless a pre-allocated string was provided to | |||
| 3497 | @code{bindat-pack}, in which case that byte is left unmodified. The | 3500 | @code{bindat-pack}, in which case that byte is left unmodified. The |
| 3498 | length of the packed output is the length of the input string plus one | 3501 | length of the packed output is the length of the input string plus one |
| 3499 | (for the null terminator). The input string must not contain any null | 3502 | (for the null terminator). The input string must not contain any null |
| 3500 | bytes. When unpacking, the resulting string contains all bytes up to | 3503 | bytes. If the input string is multibyte with only ASCII and |
| 3501 | (but excluding) the null byte. | 3504 | @code{eight-bit} characters, it is converted to unibyte before it is |
| 3505 | packed; other multibyte strings signal an error. When unpacking, the | ||
| 3506 | resulting string contains all bytes up to (but excluding) the null | ||
| 3507 | byte. | ||
| 3502 | 3508 | ||
| 3503 | @quotation Caution | 3509 | @quotation Caution |
| 3504 | If a pre-allocated string is provided to @code{bindat-pack}, the | 3510 | If a pre-allocated string is provided to @code{bindat-pack}, the |
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 84d5ea1e3b3..2d6589b52de 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el | |||
| @@ -435,12 +435,14 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." | |||
| 435 | (bindat--pack-u32r (ash v -32))) | 435 | (bindat--pack-u32r (ash v -32))) |
| 436 | 436 | ||
| 437 | (defun bindat--pack-str (len v) | 437 | (defun bindat--pack-str (len v) |
| 438 | (dotimes (i (min len (length v))) | 438 | (let ((v (string-to-unibyte v))) |
| 439 | (aset bindat-raw (+ bindat-idx i) (aref v i))) | 439 | (dotimes (i (min len (length v))) |
| 440 | (setq bindat-idx (+ bindat-idx len))) | 440 | (aset bindat-raw (+ bindat-idx i) (aref v i))) |
| 441 | (setq bindat-idx (+ bindat-idx len)))) | ||
| 441 | 442 | ||
| 442 | (defun bindat--pack-strz (v) | 443 | (defun bindat--pack-strz (v) |
| 443 | (let ((len (length v))) | 444 | (let* ((v (string-to-unibyte v)) |
| 445 | (len (length v))) | ||
| 444 | (dotimes (i len) | 446 | (dotimes (i len) |
| 445 | (aset bindat-raw (+ bindat-idx i) (aref v i))) | 447 | (aset bindat-raw (+ bindat-idx i) (aref v i))) |
| 446 | (setq bindat-idx (+ bindat-idx len 1)))) | 448 | (setq bindat-idx (+ bindat-idx len 1)))) |
diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 1ce402977f5..8bb3baa485e 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el | |||
| @@ -188,6 +188,22 @@ | |||
| 188 | (apply #'bindat-pack (append (car tc) (list prealloc))) | 188 | (apply #'bindat-pack (append (car tc) (list prealloc))) |
| 189 | (should (equal prealloc (cdr tc)))))) | 189 | (should (equal prealloc (cdr tc)))))) |
| 190 | 190 | ||
| 191 | (ert-deftest bindat-test--str-strz-multibyte () | ||
| 192 | (dolist (spec (list (bindat-type str 2) | ||
| 193 | (bindat-type strz 2) | ||
| 194 | (bindat-type strz))) | ||
| 195 | (should (equal (bindat-pack spec (string-to-multibyte "x")) "x\0")) | ||
| 196 | (should (equal (bindat-pack spec (string-to-multibyte "\xff")) "\xff\0")) | ||
| 197 | (should-error (bindat-pack spec "💩")) | ||
| 198 | (should-error (bindat-pack spec "\N{U+ff}"))) | ||
| 199 | (dolist (spec (list '((x str 2)) '((x strz 2)))) | ||
| 200 | (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "x")))) | ||
| 201 | "x\0")) | ||
| 202 | (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "\xff")))) | ||
| 203 | "\xff\0")) | ||
| 204 | (should-error (bindat-pack spec '((x . "💩")))) | ||
| 205 | (should-error (bindat-pack spec '((x . "\N{U+ff}")))))) | ||
| 206 | |||
| 191 | (let ((spec (bindat-type strz 2))) | 207 | (let ((spec (bindat-type strz 2))) |
| 192 | (ert-deftest bindat-test--strz-fixedlen-len () | 208 | (ert-deftest bindat-test--strz-fixedlen-len () |
| 193 | (should (equal (bindat-length spec "") 2)) | 209 | (should (equal (bindat-length spec "") 2)) |