Utilizando el código del boletín:
ws_ctx_t *do_handshake(int sock) {
char handshake[4096], response[4096], sha1[29], trailer[17];
[...]
offset = 0;
for (i = 0; i < 10; i++) {
len = ws_recv(ws_ctx, handshake+offset, 4096);
if (len == 0) {
handler_emsg("Client closed during handshake\n");
return NULL;
}
offset += len;
handshake[offset] = 0;
if (strstr(handshake, "\r\n\r\n")) {
break;
}
usleep(10);
}
[...]
}
- offset = 0
- ws_recv (ws_ctx, handshake + 0, 4096) = > 4096
- offset = 4096
- apretón de manos [4096] = 0; // Escritura fuera de límites.
- no se encontró doble CRLF, bucle
- ws_recv (ws_ctx, handshake + 4096, 4096) = > completamente fuera de los límites escribe.
El bucle parece haber sido diseñado con el supuesto de que solo lo haría debido a la recepción de datos insuficientes. Al tirar montones de datos en él, de todos modos se repitió, pero después de la primera pasada ya no tenía la memoria adecuadamente restringida.
El tercer parámetro debería haber sido 4096 - offset
, que representa la cantidad de espacio restante, no el espacio total del búfer (ya que ws_recv no obtuvo el búfer total a menos que offset == 0). (O necesitaban reasignar, etcétera).