Skip to content

Commit

Permalink
Strict (un)marshal size checking
Browse files Browse the repository at this point in the history
* xcb-types.el (xcb:marshal xcb:-struct): Fail encoding if expected size
  is match the size of the encoded struct.
  (xcb:unmarshal xcb:-struct): Fail decoding if the expected size is
  less than the number of bytes read or more than the number of bytes
  available to read.
  (xcb:marshal xcb:-union): Fail encoding if the expected size is less
  than the size of the encoded union.
  • Loading branch information
Stebalien committed Jan 17, 2024
1 parent a59dde8 commit 8430baa
Showing 1 changed file with 28 additions and 6 deletions.
34 changes: 28 additions & 6 deletions xcb-types.el
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,14 @@ Consider let-bind it rather than change its global value."))
(length result))))
(when (eq type 'xcb:-switch) ;xcb:-switch always finishes a struct
(throw 'break 'nil)))))
;; If we specify a size, verify that it matches the actual size.
(when-let* ((size-exp (slot-value slots '~size))
(size (eval size-exp `((obj . ,slots)))))
(unless (length= result size)
(error "[XCB] Unexpected size for type %s: got %d, expected %d"
(type-of obj)
(length result)
size)))
result))

(cl-defmethod xcb:-marshal-field ((obj xcb:-struct) type value &optional pos)
Expand Down Expand Up @@ -640,11 +648,21 @@ The optional argument CTX is for <paramref>."
(setq result (+ result (cadr tmp)))
(when (eq type 'xcb:-switch) ;xcb:-switch always finishes a struct
(throw 'break 'nil)))))
(if-let ((size (slot-value obj '~size)))
;; Let the struct compute it's size if a length field is specified. This lets us skip
;; unknown fields.
(eval (slot-value obj '~size) `((obj . ,obj)))
result)))
;; Let the struct compute it's size if a length field is specified. This lets us skip unknown
;; fields.
(when-let* ((size-exp (slot-value obj '~size))
(size (eval size-exp `((obj . ,obj)))))
;; Make sure the stated size is reasonable.
(cond
((< size result)
(error "[XCB] Object of type `%s' specified a size (%d) less than the number of bytes read (%d)"
(type-of obj) size result))
((length< byte-array (- size result))
(error "[XCB] Object of type `%s' specified a size (%d) greater than the size of the input (%d)"
(type-of obj) size (+ result (length byte-array)))))
;; Skip any additional bytes.
(setq result size))
result))

(cl-defmethod xcb:-unmarshal-field ((obj xcb:-struct) type data offset
initform &optional ctx total-length)
Expand Down Expand Up @@ -868,8 +886,12 @@ This result is converted from the first bounded slot."
(slot-value obj name)))
(when (> (length tmp) (length result))
(setq result tmp))))
(when (> size (length result))
(cond
((length< result size)
(setq result (vconcat result (make-vector (- size (length result)) 0))))
((length> result size)
(error "[XCB] Marshaled enum `%s' is larger than its declared size (%d > %d)"
(type-of obj) (length result) size)))
result))
;;
(cl-defmethod xcb:unmarshal ((obj xcb:-union) byte-array &optional ctx
Expand Down

0 comments on commit 8430baa

Please sign in to comment.