]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
AST-2018-006: Properly handle WebSocket frames with 0 length payload.
authorSean Bright <sean.bright@gmail.com>
Mon, 5 Feb 2018 22:46:26 +0000 (17:46 -0500)
committerBenjamin Keith Ford <bford@digium.com>
Wed, 21 Feb 2018 16:32:18 +0000 (10:32 -0600)
In ast_websocket_read() we were not adequately checking that the
payload_len was non-zero before passing it to ws_safe_read(). Calling
ws_safe_read with a len argument of 0 will result in a busy loop until
the underlying socket is closed.

ASTERISK-27658 #close

Change-Id: I9d59f83bc563f711df1a6197c57de473f6b0663a

res/res_http_websocket.c

index 9e5506f2a7a1d81d74805ce3c30c571a34bb651f..aaaba7d1307286bc38800c88fd550e899c87939a 100644 (file)
@@ -495,13 +495,20 @@ const char * AST_OPTIONAL_API_NAME(ast_websocket_session_id)(struct ast_websocke
  * Note during the header parsing stage we try to read in small chunks just what we need, this
  * is buffered data anyways, no expensive syscall required most of the time ...
  */
-static inline int ws_safe_read(struct ast_websocket *session, char *buf, int len, enum ast_websocket_opcode *opcode)
+static inline int ws_safe_read(struct ast_websocket *session, char *buf, size_t len, enum ast_websocket_opcode *opcode)
 {
        ssize_t rlen;
        int xlen = len;
        char *rbuf = buf;
        int sanity = 10;
 
+       ast_assert(len > 0);
+
+       if (!len) {
+               errno = EINVAL;
+               return -1;
+       }
+
        ao2_lock(session);
        if (!session->stream) {
                ao2_unlock(session);
@@ -615,9 +622,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_read)(struct ast_websocket *session, cha
                        return -1;
                }
 
-               if (ws_safe_read(session, *payload, *payload_len, opcode)) {
-                       return -1;
+               if (*payload_len) {
+                       if (ws_safe_read(session, *payload, *payload_len, opcode)) {
+                               return -1;
+                       }
                }
+
                /* If a mask is present unmask the payload */
                if (mask_present) {
                        unsigned int pos;