harden some len checks

This commit is contained in:
Sergio R. Caprile committed 2026-07-13 17:51:50 -03:00
1 parent bc69625a5e
commit 2ec27994f4
3 files changed
+54 -32

No files matched your search

+27 -16
View File
@@ -8493,24 +8493,31 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
*end = (uint8_t *) &pkt->pay.buf[pkt->pay.len];
// min header length checked at payload calculation, options are optional
if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return;
while (p + 1 < end && p[0] != 255) { // Parse options, get #1; RFC-2132 9
if (p[0] == 1 && p[1] == 4 && p + 6 < end) { // Mask, 3.3
while (p < end && p[0] != 255) { // RFC-2132 9
if (p[0] == 0) { p++; continue; } // Pad
if ((size_t) (end - p) < 2 || (size_t) (end - p) < 2U + p[1]) break;
if (p[0] == 1) { // Mask, 3.3
if (p[1] != 4) break;
memcpy(&mask, p + 2, sizeof(mask));
} else if (p[0] == 3 && dhcp_opt_len_ok(p[1], p, end)) { // GW, 3.5
} else if (p[0] == 3) { // GW, 3.5
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&gw, p + 2, sizeof(gw));
ip = pkt->dhcp->yiaddr;
} else if (ifp->enable_req_dns && p[0] == 6 &&
dhcp_opt_len_ok(p[1], p, end)) { // DNS, 3.8
} else if (ifp->enable_req_dns && p[0] == 6) { // DNS, 3.8
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&dns, p + 2, sizeof(dns));
} else if (ifp->enable_req_sntp && p[0] == 42 &&
dhcp_opt_len_ok(p[1], p, end)) { // SNTP, 8.3
} else if (ifp->enable_req_sntp && p[0] == 42) { // SNTP, 8.3
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&sntp, p + 2, sizeof(sntp));
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
} else if (p[0] == 51) { // Lease
if (p[1] != 4) break;
memcpy(&lease, p + 2, sizeof(lease));
lease = mg_ntohl(lease);
} else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type
} else if (p[0] == 53) { // Msg Type
if (p[1] != 1) break;
msgtype = p[2];
} else if (p[0] == 54 && p[1] == 4 && p + 6 < end) { // Server id 9.7
} else if (p[0] == 54) { // Server id 9.7
if (p[1] != 4) break;
memcpy(&owner, p + 2, sizeof(sntp)); // This is the lease owner
}
p += p[1] + 2;
@@ -8565,8 +8572,11 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// min header length checked at payload calculation, options are optional
res.yiaddr = ifp->ip;
((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
while (p + 1 < end && p[0] != 255) { // Parse options
if (p[0] == 53 && p[1] == 1 && p + 2 < end) { // Message type
while (p < end && p[0] != 255) { // Parse options
if (p[0] == 0) { p++; continue; } // Pad
if ((size_t) (end - p) < 2 || (size_t) (end - p) < 2U + p[1]) break;
if (p[0] == 53) { // Message type
if (p[1] != 1) break;
op = p[2];
}
p += p[1] + 2;
@@ -17350,6 +17360,7 @@ static int mg_tls_client_recv_hello(struct mg_connection *c) {
if (rio->len < 5 + 39 + 32 + 3 + 2) goto fail;
msgsz = MG_LOAD_BE16(rio->buf + 3);
if (msgsz > rio->len - 5) goto fail;
mg_sha256_update(&tls->sha256, rio->buf + 5, msgsz);
ext_len = MG_LOAD_BE16(rio->buf + 5 + 39 + 32 + 3);
@@ -18221,7 +18232,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end,
// Long form length
uint8_t len_bytes = len & 0x7F;
MG_VERBOSE(("DER INT: long form, %d length bytes", len_bytes));
if (end - *p < len_bytes) {
if (len_bytes == 0 || len_bytes > 4 || (size_t) (end - *p) < len_bytes) {
MG_VERBOSE(("DER INT: not enough bytes for length"));
return -1;
}
@@ -18234,7 +18245,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end,
MG_VERBOSE(("DER INT: length=%u, remaining=%d", len, (int) (end - *p)));
if (end - *p < (long) len) {
if ((size_t) (end - *p) < len) {
MG_VERBOSE(("DER INT: length exceeds remaining bytes"));
return -1;
}
@@ -18335,7 +18346,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz,
// Long form length
uint8_t i, len_bytes = seq_len & 0x7F;
MG_VERBOSE(("Long form length: %d bytes", len_bytes));
if (end - p < len_bytes) {
if (len_bytes == 0 || len_bytes > 4 || (size_t) (end - p) < len_bytes) {
MG_ERROR(("Not enough bytes for long form length"));
return -1;
}
@@ -18349,7 +18360,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz,
MG_VERBOSE(
("SEQUENCE length: %u, total DER size: %u", seq_len, (unsigned) dersz));
if (end - p < (long) seq_len) {
if ((size_t) (end - p) < seq_len) {
MG_ERROR(("SEQUENCE length exceeds buffer"));
return -1;
}
+22 -12
View File
@@ -666,24 +666,31 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
*end = (uint8_t *) &pkt->pay.buf[pkt->pay.len];
// min header length checked at payload calculation, options are optional
if (memcmp(&pkt->dhcp->xid, ifp->mac + 2, sizeof(pkt->dhcp->xid))) return;
while (p + 1 < end && p[0] != 255) { // Parse options, get #1; RFC-2132 9
if (p[0] == 1 && p[1] == 4 && p + 6 < end) { // Mask, 3.3
while (p < end && p[0] != 255) { // RFC-2132 9
if (p[0] == 0) { p++; continue; } // Pad
if ((size_t) (end - p) < 2 || (size_t) (end - p) < 2U + p[1]) break;
if (p[0] == 1) { // Mask, 3.3
if (p[1] != 4) break;
memcpy(&mask, p + 2, sizeof(mask));
} else if (p[0] == 3 && dhcp_opt_len_ok(p[1], p, end)) { // GW, 3.5
} else if (p[0] == 3) { // GW, 3.5
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&gw, p + 2, sizeof(gw));
ip = pkt->dhcp->yiaddr;
} else if (ifp->enable_req_dns && p[0] == 6 &&
dhcp_opt_len_ok(p[1], p, end)) { // DNS, 3.8
} else if (ifp->enable_req_dns && p[0] == 6) { // DNS, 3.8
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&dns, p + 2, sizeof(dns));
} else if (ifp->enable_req_sntp && p[0] == 42 &&
dhcp_opt_len_ok(p[1], p, end)) { // SNTP, 8.3
} else if (ifp->enable_req_sntp && p[0] == 42) { // SNTP, 8.3
if (!dhcp_opt_len_ok(p[1], p, end)) break;
memcpy(&sntp, p + 2, sizeof(sntp));
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
} else if (p[0] == 51) { // Lease
if (p[1] != 4) break;
memcpy(&lease, p + 2, sizeof(lease));
lease = mg_ntohl(lease);
} else if (p[0] == 53 && p[1] == 1 && p + 6 < end) { // Msg Type
} else if (p[0] == 53) { // Msg Type
if (p[1] != 1) break;
msgtype = p[2];
} else if (p[0] == 54 && p[1] == 4 && p + 6 < end) { // Server id 9.7
} else if (p[0] == 54) { // Server id 9.7
if (p[1] != 4) break;
memcpy(&owner, p + 2, sizeof(sntp)); // This is the lease owner
}
p += p[1] + 2;
@@ -738,8 +745,11 @@ static void rx_dhcp_server(struct mg_tcpip_if *ifp, struct pkt *pkt) {
// min header length checked at payload calculation, options are optional
res.yiaddr = ifp->ip;
((uint8_t *) (&res.yiaddr))[3]++; // Offer our IP + 1
while (p + 1 < end && p[0] != 255) { // Parse options
if (p[0] == 53 && p[1] == 1 && p + 2 < end) { // Message type
while (p < end && p[0] != 255) { // Parse options
if (p[0] == 0) { p++; continue; } // Pad
if ((size_t) (end - p) < 2 || (size_t) (end - p) < 2U + p[1]) break;
if (p[0] == 53) { // Message type
if (p[1] != 1) break;
op = p[2];
}
p += p[1] + 2;
+5 -4
View File
@@ -1321,6 +1321,7 @@ static int mg_tls_client_recv_hello(struct mg_connection *c) {
if (rio->len < 5 + 39 + 32 + 3 + 2) goto fail;
msgsz = MG_LOAD_BE16(rio->buf + 3);
if (msgsz > rio->len - 5) goto fail;
mg_sha256_update(&tls->sha256, rio->buf + 5, msgsz);
ext_len = MG_LOAD_BE16(rio->buf + 5 + 39 + 32 + 3);
@@ -2192,7 +2193,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end,
// Long form length
uint8_t len_bytes = len & 0x7F;
MG_VERBOSE(("DER INT: long form, %d length bytes", len_bytes));
if (end - *p < len_bytes) {
if (len_bytes == 0 || len_bytes > 4 || (size_t) (end - *p) < len_bytes) {
MG_VERBOSE(("DER INT: not enough bytes for length"));
return -1;
}
@@ -2205,7 +2206,7 @@ static int mg_rsa_parse_der_int(const uint8_t **p, const uint8_t *end,
MG_VERBOSE(("DER INT: length=%u, remaining=%d", len, (int) (end - *p)));
if (end - *p < (long) len) {
if ((size_t) (end - *p) < len) {
MG_VERBOSE(("DER INT: length exceeds remaining bytes"));
return -1;
}
@@ -2306,7 +2307,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz,
// Long form length
uint8_t i, len_bytes = seq_len & 0x7F;
MG_VERBOSE(("Long form length: %d bytes", len_bytes));
if (end - p < len_bytes) {
if (len_bytes == 0 || len_bytes > 4 || (size_t) (end - p) < len_bytes) {
MG_ERROR(("Not enough bytes for long form length"));
return -1;
}
@@ -2320,7 +2321,7 @@ static int mg_rsa_parse_key(const uint8_t *der, size_t dersz,
MG_VERBOSE(
("SEQUENCE length: %u, total DER size: %u", seq_len, (unsigned) dersz));
if (end - p < (long) seq_len) {
if ((size_t) (end - p) < seq_len) {
MG_ERROR(("SEQUENCE length exceeds buffer"));
return -1;
}