branch: externals/websocket
commit 0bf139ff46b8a01ae071099c9d5c28b44f07d4dd
Author: Andrew Hyatt <[email protected]>
Commit: Andrew Hyatt <[email protected]>
Fix tests and behavior
With the new bindat code, we don't need to error on certain things that we
can
now handle.
The code itself had a few issues - one where we were losing the header
match,
and the other where the code didn't multiply the length of the bindat uint
by 8.
Also added a few more checks.
---
websocket-test.el | 27 +++++++++++++++++----------
websocket.el | 35 +++++++++++++++++++++++++++--------
2 files changed, 44 insertions(+), 18 deletions(-)
diff --git a/websocket-test.el b/websocket-test.el
index 2e71e9093d..d9d6976180 100644
--- a/websocket-test.el
+++ b/websocket-test.el
@@ -49,7 +49,10 @@
(should (equal #x101 (websocket-get-bytes "\x1\x1" 2)))
(should (equal #xffffff
(websocket-get-bytes "\x0\x0\x0\x0\x0\xFF\xFF\xFF" 8)))
- (should-error (websocket-get-bytes "\x0\x0\x0\x1\x0\x0\x0\x1" 8)
+ (unless (fboundp 'bindat-type)
+ (should-error (websocket-get-bytes "\x0\x0\x0\x1\x0\x0\x0\x1" 8)
+ :type 'websocket-unparseable-frame))
+ (should-error (websocket-get-bytes "\x80\x0\x0\x0\x0\x0\x0\x0" 8)
:type 'websocket-unparseable-frame)
(should-error (websocket-get-bytes "\x0\x0\x0" 3))
(should-error (websocket-get-bytes "\x0" 2) :type
'websocket-unparseable-frame))
@@ -266,20 +269,21 @@
(websocket-create-headers "ws://www.example.com:123/path" "key" nil nil
nil)))))
(ert-deftest websocket-process-headers ()
- (cl-flet ((url-cookie-handle-set-cookie
- (text)
- (should (equal text "foo=bar;"))
- ;; test that we have set the implicit buffer variable needed
- ;; by url-cookie-handle-set-cookie
- (should (equal url-current-object
- (url-generic-parse-url
"ws://example.com/path")))))
+ (cl-letf (((symbol-function 'url-cookie-handle-set-cookie)
+ (lambda (text)
+ (should (equal text "foo=bar;"))
+ ;; test that we have set the implicit buffer variable needed
+ ;; by url-cookie-handle-set-cookie
+ (should (equal url-current-object
+ (url-generic-parse-url
"ws://example.com/path"))))))
(websocket-process-headers "ws://example.com/path"
(concat
"HTTP/1.1 101 Switching Protocols\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Set-Cookie: foo=bar;\r\n\r\n")))
- (cl-flet ((url-cookie-handle-set-cookie (_text) (should nil)))
+ (cl-letf (((symbol-function 'url-cookie-handle-set-cookie)
+ (lambda (_text) (should nil))))
(websocket-process-headers "ws://example.com/path"
"HTTP/1.1 101 Switching Protocols\r\n")))
@@ -344,9 +348,12 @@
(should (equal 70000 (websocket-get-bytes (websocket-to-bytes 70000 8) 8)))
;; Only run if the number we're testing with is not more than the system can
;; handle.
- (if (equal "1" (calc-eval (format "536870912 < %d" most-positive-fixnum)))
+ (if (and (not (fboundp 'bindat-type))
+ (equal "1" (calc-eval (format "536870912 < %d"
most-positive-fixnum))))
(should-error (websocket-to-bytes 536870912 8)
:type 'websocket-frame-too-large))
+ (should-error (websocket-to-bytes (expt 2 63) 8)
+ :type 'websocket-frame-too-large)
(should-error (websocket-to-bytes 30 3))
(should-error (websocket-to-bytes 300 1))
;; I'd like to test the error for 32-byte systems on 8-byte lengths,
diff --git a/websocket.el b/websocket.el
index a601ab569c..5f2b745d60 100644
--- a/websocket.el
+++ b/websocket.el
@@ -200,8 +200,17 @@ power of 2, up to 8.
In Emacs<28, we support getting frames only up to 536870911 bytes (2^29 - 1),
approximately 537M long."
+ (unless (memq n '(1 2 4 8))
+ (error "websocket-get-bytes: Unknown N: %S" n))
(websocket--if-when-compile (fboundp 'bindat-type) ;Emacsā„28
- (bindat-unpack (bindat-type uint (* 8 n)) s)
+ (condition-case nil
+ (let ((val (bindat-unpack (bindat-type uint (* 8 n)) s)))
+ (if (and (= n 8) (> (ash val -63) 0))
+ (signal 'websocket-unparseable-frame
+ (list "Frame value found too large to parse!"))
+ val))
+ (args-out-of-range (signal 'websocket-unparseable-frame
+ (list "Frame ended before all bytes were
read!"))))
(if (= n 8)
(let* ((32-bit-parts
(bindat-get-field (bindat-unpack '((:val vec 2 u32)) s) :val))
@@ -236,13 +245,18 @@ NBYTES much be a power of 2, up to 8.
In Emacs<28, this supports encoding values only up to 536870911 bytes
\(2^29 - 1), approximately 537M long."
+ (unless (memq nbytes '(1 2 4 8))
+ (error "websocket-to-bytes: Unknown NBYTES: %S" nbytes))
(unless (= 0 (ash val (- (* 8 nbytes))))
;; not a user-facing error, this must be caused from an error in
;; this library
(error "websocket-to-bytes: Value %d could not be expressed in %d bytes"
val nbytes))
(websocket--if-when-compile (fboundp 'bindat-type)
- (bindat-pack (bindat-type uint (* 8 nbytes)) val)
+ (progn
+ (if (and (= nbytes 8) (> (ash val -63) 0))
+ (signal 'websocket-frame-too-large (list val)))
+ (bindat-pack (bindat-type uint (* 8 nbytes)) val))
(if (= nbytes 8)
(progn
(let* ((hi-32bits (ash val -32))
@@ -284,8 +298,12 @@ many bytes were consumed from the string."
(len2len unit (pcase len1 (127 8) (126 2) (_ 0)))
(len2 uint (progn
(websocket-ensure-length s (1+ len2len))
- len2len))
- :unpack-val (cons (if (zerop len2) len1 len2) (1+ len2len)))
+ (* 8 len2len)))
+ :unpack-val (cons (if (< len1 126) len1
+ (if (and (= len2len 8) (> (ash len2 -63) 0))
+ (signal 'websocket-unparseable-frame (list
"MSB must be 0 for 64-bit length"))
+ len2))
+ (1+ len2len)))
s)
(let* ((initial-val (logand 127 (aref s 0))))
(cond ((= initial-val 127)
@@ -766,10 +784,11 @@ to the websocket protocol.
(defun websocket-process-headers (url headers)
"On opening URL, process the HEADERS sent from the server."
(when (string-match "Set-Cookie: \\(.*\\)\r\n" headers)
- ;; The url-current-object is assumed to be set by
- ;; url-cookie-handle-set-cookie.
- (let ((url-current-object (url-generic-parse-url url)))
- (url-cookie-handle-set-cookie (match-string 1 headers)))))
+ (let ((cookie (match-string 1 headers))
+ ;; The url-current-object is assumed to be set by
+ ;; url-cookie-handle-set-cookie.
+ (url-current-object (url-generic-parse-url url)))
+ (url-cookie-handle-set-cookie cookie))))
(defun websocket-outer-filter (websocket output)
"Filter the WEBSOCKET server's OUTPUT.