security: replace unsafe atoi() with validated parsing in websocket

Input Validation: High

The WebSocket HTTP reply parser used atoi() to parse the Content-Length
header from network data. atoi() does not detect overflow or invalid
input, and its int return value was assigned to a size_t, meaning a
negative value from a malicious server would silently convert to a very
large unsigned value, potentially causing excessive memory allocation.

Replaced with spa_atou32() which validates the entire string is a valid
number and fits in uint32_t, plus an explicit upper bound (16 MB) on
content length to prevent resource exhaustion.

Similarly, pw_websocket_listen() used atoi() to parse the port number
into a uint16_t without validation. Replaced with spa_atou32() and a
range check against 65535.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Wim Taymans 2026-04-27 16:55:57 +02:00
parent aaa7076b52
commit 7465199fff

View file

@ -518,8 +518,12 @@ static int receive_http_reply(struct pw_websocket_connection *conn,
return -EPROTO;
}
}
else if (spa_streq(key, "Content-Length"))
conn->content_length = atoi(value);
else if (spa_streq(key, "Content-Length")) {
uint32_t cl;
if (!spa_atou32(value, &cl, 10) || cl > 0xFFFFFF)
return -EPROTO;
conn->content_length = cl;
}
} else {
conn->data_state++;
need = conn->content_length;
@ -907,7 +911,12 @@ int pw_websocket_listen(struct pw_websocket *ws, void *user,
{
int res;
struct server *server;
uint16_t port = atoi(service);
uint32_t port32;
uint16_t port;
if (!spa_atou32(service, &port32, 10) || port32 > 65535)
return -EINVAL;
port = (uint16_t)port32;
if ((server = calloc(1, sizeof(struct server))) == NULL)
return -errno;