From 5e787114678faa386c2b4b869967b61856d3e8d6 Mon Sep 17 00:00:00 2001
From: Sergey Lyubka <valenok@gmail.com>
Date: Sat, 18 May 2013 10:29:03 +0100
Subject: [PATCH] Fixed masking in websocket code

---
 mongoose.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/mongoose.c b/mongoose.c
index a4618322a..6194ded43 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -3818,9 +3818,9 @@ static void send_websocket_handshake(struct mg_connection *conn) {
 
 static void read_websocket(struct mg_connection *conn) {
   unsigned char *buf = (unsigned char *) conn->buf + conn->request_len;
-  int n, stop = 0;
+  int bits, n, stop = 0;
   size_t i, len, mask_len, data_len, header_len, body_len;
-  char mem[4 * 1024], *data;
+  char mem[4 * 1024], mask[4], *data;
 
   assert(conn->content_len == 0);
   while (!stop) {
@@ -3841,6 +3841,14 @@ static void read_websocket(struct mg_connection *conn) {
       }
     }
 
+    // Data layout is as follows:
+    //  conn->buf               buf
+    //     v                     v              frame1           | frame2
+    //     |---------------------|----------------|--------------|-------
+    //     |                     |<--header_len-->|<--data_len-->|
+    //     |<-conn->request_len->|<-----body_len----------->|
+    //     |<-------------------conn->data_len------------->|
+
     if (header_len > 0) {
       // Allocate space to hold websocket payload
       data = mem;
@@ -3850,6 +3858,10 @@ static void read_websocket(struct mg_connection *conn) {
         break;
       }
 
+      // Save mask and bits, otherwise it may be clobbered by memmove below
+      bits = buf[0];
+      memcpy(mask, buf + header_len - mask_len, mask_len);
+
       // Read frame payload into the allocated buffer.
       assert(body_len >= header_len);
       if (data_len + header_len > body_len) {
@@ -3868,15 +3880,15 @@ static void read_websocket(struct mg_connection *conn) {
       // Apply mask if necessary
       if (mask_len > 0) {
         for (i = 0; i < data_len; i++) {
-          data[i] ^= buf[header_len - mask_len + (i % 4)];
+          data[i] ^= mask[i % 4];
         }
       }
 
       // Exit the loop if callback signalled to exit,
       // or "connection close" opcode received.
       if ((conn->ctx->callbacks.websocket_data != NULL &&
-          !conn->ctx->callbacks.websocket_data(conn, buf[0], data, data_len)) ||
-          (buf[0] & 0xf) == 8) {  // Opcode == 8, connection close
+          !conn->ctx->callbacks.websocket_data(conn, bits, data, data_len)) ||
+          (bits & 0xf) == 8) {  // Opcode == 8, connection close
         stop = 1;
       }
 
-- 
GitLab