Perform validation prior to send buffer from the server to the client.
@@ -114,6 +114,50 @@ verify_utf8 (uint32_t * state, const char *str, int len)
return *state;
}
+/* Decode a character maintaining state and a byte, and returns the
+ * state achieved after processing the byte.
+ *
+ * The state after the by has been processed is returned. */
+static uint32_t
+utf8_decode (uint32_t * state, uint32_t * p, uint32_t b)
+{
+ uint32_t type = utf8d[(uint8_t) b];
+
+ *p = (*state != UTF8_VALID) ? (b & 0x3fu) | (*p << 6) : (0xff >> type) & (b);
+ *state = utf8d[256 + *state * 16 + type];
+
+ return *state;
+}
+
+/* Replace malformed sequences with a substitute character.
+ *
+ * On success, it replaces the whole sequence and return a malloc'd buffer. */
+static char *
+sanitize_utf8 (const char *str, int len)
+{
+ char *buf = NULL;
+ uint32_t state = UTF8_VALID, prev = UTF8_VALID, cp = 0;
+ int i = 0, j = 0;
+
+ buf = xcalloc (len + 1, sizeof (char));
+ for (; i < len; prev = state, ++i) {
+ switch (utf8_decode (&state, &cp, (unsigned char) str[i])) {
+ case UTF8_INVAL:
+ buf[j++] = '?';
+ state = UTF8_VALID;
+ if (prev != UTF8_VALID)
+ --i;
+ break;
+ default:
+ /* UTF8_VALID + continuation bytes */
+ buf[j++] = str[i];
+ break;
+ }
+ }
+
+ return buf;
+}
+
/* Allocate memory for a websocket server */
static WSServer *
new_wsserver (void)
@@ -1550,7 +1594,12 @@ ws_get_handshake (WSClient * client, WSServer * server)
int
ws_send_data (WSClient * client, WSOpcode opcode, const char *p, int sz)
{
- ws_send_frame (client, opcode, p, sz);
+ char *buf = NULL;
+
+ buf = sanitize_utf8 (p, sz);
+ ws_send_frame (client, opcode, buf, sz);
+ free (buf);
+
return 0;
}
