summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/bindat.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/bindat.el')
-rw-r--r--lisp/emacs-lisp/bindat.el45
1 files changed, 22 insertions, 23 deletions
diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el
index 9ba89a5e3fe..0ecac3d52aa 100644
--- a/lisp/emacs-lisp/bindat.el
+++ b/lisp/emacs-lisp/bindat.el
@@ -440,17 +440,26 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
(aset bindat-raw (+ bindat-idx i) (aref v i)))
(setq bindat-idx (+ bindat-idx len))))
-(defun bindat--pack-strz (v)
+(defun bindat--pack-strz (len v)
(let* ((v (string-to-unibyte v))
- (len (length v)))
- (dotimes (i len)
- (when (= (aref v i) 0)
- ;; Alternatively we could pretend that this was the end of
- ;; the string and stop packing, but then bindat-length would
- ;; 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)))
- (setq bindat-idx (+ bindat-idx len 1))))
+ (vlen (length v)))
+ ;; Explicitly write a null terminator (if there's room) in case
+ ;; the user provided a pre-allocated string to `bindat-pack' that
+ ;; wasn't already zeroed.
+ (when (or (null len) (< vlen len))
+ (aset bindat-raw (+ bindat-idx vlen) 0))
+ (if len
+ ;; When len is specified, behave the same as the str type
+ ;; (except for the null terminator possibly written above).
+ (bindat--pack-str len v)
+ (dotimes (i vlen)
+ (when (= (aref v i) 0)
+ ;; Alternatively we could pretend that this was the end of
+ ;; the string and stop packing, but then bindat-length would
+ ;; 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)))
+ (setq bindat-idx (+ bindat-idx vlen 1)))))
(defun bindat--pack-bits (len v)
(let ((bnum (1- (* 8 len))) j m)
@@ -479,7 +488,8 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..."
('u24r (bindat--pack-u24r v))
('u32r (bindat--pack-u32r v))
('bits (bindat--pack-bits len v))
- ((or 'str 'strz) (bindat--pack-str len v))
+ ('str (bindat--pack-str len v))
+ ('strz (bindat--pack-strz len v))
('vec
(let ((l (length v)) (vlen 1))
(if (consp vectype)
@@ -696,18 +706,7 @@ is the name of a variable that will hold the value we need to pack.")
((numberp len) len)
;; General expression support.
(t `(or ,len (1+ (length ,val)))))))
- (`(pack . ,args)
- ;; When len is specified, behave the same as the str type since we don't
- ;; actually add the terminating zero anyway (because we rely on the fact
- ;; that `bindat-raw' was presumably initialized with all-zeroes before we
- ;; started).
- (cond ; Same optimizations as 'length above.
- ((null len) `(bindat--pack-strz . ,args))
- ((numberp len) `(bindat--pack-str ,len . ,args))
- (t (macroexp-let2 nil len len
- `(if ,len
- (bindat--pack-str ,len . ,args)
- (bindat--pack-strz . ,args))))))))
+ (`(pack . ,args) `(bindat--pack-strz ,len . ,args))))
(cl-defmethod bindat--type (op (_ (eql 'bits)) len)
(bindat--pcase op