Commit 6f49c1f209d for php.net

commit 6f49c1f209d89870cb98ea3150ede89dbcfadc5f
Author: Lazizbek Ergashev <lazerg2@gmail.com>
Date:   Mon Sep 7 21:07:06 2026 +0100

    Fix GH-23453: bad free with a context engine ID longer than 32 bytes

    netsnmp_session_set_contextEngineID() passes an emalloc()'d buffer to
    snmp_hex_to_binary() with allow_realloc set. A context engine ID longer
    than the 32-byte buffer makes net-snmp call snmp_realloc() on that
    pointer, which aborts the process.

    RFC 3411 caps the engine ID at 32 bytes anyway, so this drops
    allow_realloc: an oversized value now hits the existing "Bad engine ID
    value" warning and returns false.

    Close GH-23456

diff --git a/NEWS b/NEWS
index 056f0296b68..a9335d0840d 100644
--- a/NEWS
+++ b/NEWS
@@ -98,6 +98,10 @@ PHP                                                                        NEWS
   . Fixed bug GH-23477 (Memory leak on duplicate native Phar manifest entries).
     (Weilin Du)

+- SNMP:
+  . Fixed bug GH-23453 (SNMP::setSecurity() frees a non-malloced address with a
+    context engine ID longer than 32 bytes). (Lazizbek Ergashev)
+
 - SOAP:
   . Fixed bug GH-23447 (Segfault when a class passed to SoapServer::setClass()
     fails to initialize). (Lazizbek Ergashev)
diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c
index afbdda285ec..6277c1f3f72 100644
--- a/ext/snmp/snmp.c
+++ b/ext/snmp/snmp.c
@@ -1086,7 +1086,8 @@ static bool netsnmp_session_set_contextEngineID(struct snmp_session *s, zend_str
 	size_t	ebuf_len = 32, eout_len = 0;
 	uint8_t	*ebuf = (uint8_t *) emalloc(ebuf_len);

-	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 1, ZSTR_VAL(contextEngineID))) {
+	/* Disallow reallocation: ebuf comes from emalloc() and net-snmp would realloc() it. */
+	if (!snmp_hex_to_binary(&ebuf, &ebuf_len, &eout_len, 0, ZSTR_VAL(contextEngineID))) {
 		// TODO Promote to Error?
 		php_error_docref(NULL, E_WARNING, "Bad engine ID value '%s'", ZSTR_VAL(contextEngineID));
 		efree(ebuf);
diff --git a/ext/snmp/tests/gh23453.phpt b/ext/snmp/tests/gh23453.phpt
new file mode 100644
index 00000000000..aaa89baad18
--- /dev/null
+++ b/ext/snmp/tests/gh23453.phpt
@@ -0,0 +1,17 @@
+--TEST--
+GH-23453 (SNMP::setSecurity() frees a non-malloced address with a context engine ID longer than 32 bytes)
+--EXTENSIONS--
+snmp
+--FILE--
+<?php
+$session = new SNMP(SNMP::VERSION_3, 'localhost', 'user');
+
+// 32 bytes is the maximum length of a context engine ID
+var_dump($session->setSecurity('authPriv', 'SHA', 'authpassword12345', 'AES', 'privpassword12345', 'myContext', str_repeat('aa', 32)));
+var_dump($session->setSecurity('authPriv', 'SHA', 'authpassword12345', 'AES', 'privpassword12345', 'myContext', str_repeat('aa', 33)));
+?>
+--EXPECTF--
+bool(true)
+
+Warning: SNMP::setSecurity(): Bad engine ID value 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' in %s on line %d
+bool(false)