From a830ab1ea9955d87d93718d3961f0a2a122525d4 Mon Sep 17 00:00:00 2001 From: Thomas Vincent Date: Wed, 4 Mar 2026 08:50:40 -0800 Subject: [PATCH] ext/snmp: fix buffer overflow in suffix-as-keys OID construction The suffix-as-keys code path in php_snmp builds a dotted OID suffix string by repeatedly calling snprintf into a temporary buffer and appending with strcat into the fixed 2048-byte buf2 array. There is no bounds check, so a deeply nested OID with many large numeric components from a malicious SNMP agent could overflow the stack buffer. Replace the strcat loop with direct snprintf into buf2 at a tracked offset, breaking out of the loop if the buffer is exhausted. Signed-off-by: Thomas Vincent --- ext/snmp/snmp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 0ff8d41c1e6ce..418271cdb4717 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -525,14 +525,21 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, } else if (st & SNMP_USE_SUFFIX_AS_KEYS && st & SNMP_CMD_WALK) { snprint_objid(buf2, sizeof(buf2), vars->name, vars->name_length); if (rootlen <= vars->name_length && snmp_oid_compare(root, rootlen, vars->name, rootlen) == 0) { - buf2[0] = '\0'; + int pos = 0; count = rootlen; - while(count < vars->name_length){ - snprintf(buf, sizeof(buf), "%lu.", vars->name[count]); - strcat(buf2, buf); + while (count < vars->name_length) { + int written = snprintf(buf2 + pos, sizeof(buf2) - pos, "%lu.", vars->name[count]); + if (written < 0 || pos + written >= (int)sizeof(buf2)) { + break; + } + pos += written; count++; } - buf2[strlen(buf2) - 1] = '\0'; /* remove trailing '.' */ + if (pos > 0) { + buf2[pos - 1] = '\0'; /* remove trailing '.' */ + } else { + buf2[0] = '\0'; + } } add_assoc_zval(return_value, buf2, &snmpval); } else {