Skip to content

Commit 60eca67

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
2 parents 4eaa6f9 + 73ebc92 commit 60eca67

File tree

2 files changed

+129
-20
lines changed

2 files changed

+129
-20
lines changed

ext/snmp/snmp.c

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,31 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
624624
}
625625
/* }}} */
626626

627+
static void php_snmp_zend_string_release_from_char_pointer(char *ptr) {
628+
if (ptr) {
629+
zend_string *pptr = (zend_string *)(ptr - XtOffsetOf(zend_string, val));
630+
zend_string_release(pptr);
631+
}
632+
}
633+
634+
static void php_free_objid_query(struct objid_query *objid_query, HashTable* oid_ht, const HashTable *value_ht, int st) {
635+
if (oid_ht) {
636+
uint32_t count = zend_hash_num_elements(oid_ht);
637+
638+
for (uint32_t i = 0; i < count; i ++) {
639+
snmpobjarg *arg = &objid_query->vars[i];
640+
if (!arg->oid) {
641+
break;
642+
}
643+
if (value_ht) {
644+
php_snmp_zend_string_release_from_char_pointer(arg->value);
645+
}
646+
php_snmp_zend_string_release_from_char_pointer(arg->oid);
647+
}
648+
}
649+
efree(objid_query->vars);
650+
}
651+
627652
/* {{{ php_snmp_parse_oid
628653
*
629654
* OID parser (and type, value for SNMP_SET command)
@@ -672,10 +697,15 @@ static bool php_snmp_parse_oid(
672697
return false;
673698
}
674699
objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(oid_ht), 0);
700+
memset(objid_query->vars, 0, sizeof(snmpobjarg) * zend_hash_num_elements(oid_ht));
675701
objid_query->array_output = (st & SNMP_CMD_SET) == 0;
676702
ZEND_HASH_FOREACH_VAL(oid_ht, tmp_oid) {
677-
convert_to_string(tmp_oid);
678-
objid_query->vars[objid_query->count].oid = Z_STRVAL_P(tmp_oid);
703+
zend_string *tmp = zval_try_get_string(tmp_oid);
704+
if (!tmp) {
705+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
706+
return false;
707+
}
708+
objid_query->vars[objid_query->count].oid = ZSTR_VAL(tmp);
679709
if (st & SNMP_CMD_SET) {
680710
if (type_str) {
681711
pptr = ZSTR_VAL(type_str);
@@ -699,18 +729,24 @@ static bool php_snmp_parse_oid(
699729
}
700730
}
701731
if (idx_type < type_ht->nNumUsed) {
702-
convert_to_string(tmp_type);
703-
if (Z_STRLEN_P(tmp_type) != 1) {
732+
zend_string *type = zval_try_get_string(tmp_type);
733+
if (!type) {
734+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
735+
return false;
736+
}
737+
size_t len = ZSTR_LEN(type);
738+
char ptype = *ZSTR_VAL(type);
739+
zend_string_release(type);
740+
if (len != 1) {
704741
zend_value_error("Type must be a single character");
705-
efree(objid_query->vars);
742+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
706743
return false;
707744
}
708-
pptr = Z_STRVAL_P(tmp_type);
709-
objid_query->vars[objid_query->count].type = *pptr;
745+
objid_query->vars[objid_query->count].type = ptype;
710746
idx_type++;
711747
} else {
712-
php_error_docref(NULL, E_WARNING, "'%s': no type set", Z_STRVAL_P(tmp_oid));
713-
efree(objid_query->vars);
748+
php_error_docref(NULL, E_WARNING, "'%s': no type set", ZSTR_VAL(tmp));
749+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
714750
return false;
715751
}
716752
}
@@ -736,12 +772,16 @@ static bool php_snmp_parse_oid(
736772
}
737773
}
738774
if (idx_value < value_ht->nNumUsed) {
739-
convert_to_string(tmp_value);
740-
objid_query->vars[objid_query->count].value = Z_STRVAL_P(tmp_value);
775+
zend_string *tmp = zval_try_get_string(tmp_value);
776+
if (!tmp) {
777+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
778+
return false;
779+
}
780+
objid_query->vars[objid_query->count].value = ZSTR_VAL(tmp);
741781
idx_value++;
742782
} else {
743-
php_error_docref(NULL, E_WARNING, "'%s': no value set", Z_STRVAL_P(tmp_oid));
744-
efree(objid_query->vars);
783+
php_error_docref(NULL, E_WARNING, "'%s': no value set", ZSTR_VAL(tmp));
784+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
745785
return false;
746786
}
747787
}
@@ -754,14 +794,14 @@ static bool php_snmp_parse_oid(
754794
if (st & SNMP_CMD_WALK) {
755795
if (objid_query->count > 1) {
756796
php_snmp_error(object, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Multi OID walks are not supported!");
757-
efree(objid_query->vars);
797+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
758798
return false;
759799
}
760800
objid_query->vars[0].name_length = MAX_NAME_LEN;
761801
if (strlen(objid_query->vars[0].oid)) { /* on a walk, an empty string means top of tree - no error */
762802
if (!snmp_parse_oid(objid_query->vars[0].oid, objid_query->vars[0].name, &(objid_query->vars[0].name_length))) {
763803
php_snmp_error(object, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[0].oid);
764-
efree(objid_query->vars);
804+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
765805
return false;
766806
}
767807
} else {
@@ -773,7 +813,7 @@ static bool php_snmp_parse_oid(
773813
objid_query->vars[objid_query->offset].name_length = MAX_OID_LEN;
774814
if (!snmp_parse_oid(objid_query->vars[objid_query->offset].oid, objid_query->vars[objid_query->offset].name, &(objid_query->vars[objid_query->offset].name_length))) {
775815
php_snmp_error(object, PHP_SNMP_ERRNO_OID_PARSING_ERROR, "Invalid object identifier: %s", objid_query->vars[objid_query->offset].oid);
776-
efree(objid_query->vars);
816+
php_free_objid_query(objid_query, oid_ht, value_ht, st);
777817
return false;
778818
}
779819
}
@@ -1250,12 +1290,12 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12501290

12511291
if (session_less_mode) {
12521292
if (!netsnmp_session_init(&session, version, a1, a2, timeout, retries)) {
1253-
efree(objid_query.vars);
1293+
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
12541294
netsnmp_session_free(&session);
12551295
RETURN_FALSE;
12561296
}
12571297
if (version == SNMP_VERSION_3 && !netsnmp_session_set_security(session, a3, a4, a5, a6, a7, NULL, NULL)) {
1258-
efree(objid_query.vars);
1298+
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
12591299
netsnmp_session_free(&session);
12601300
/* Warning message sent already, just bail out */
12611301
RETURN_FALSE;
@@ -1266,7 +1306,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12661306
session = snmp_object->session;
12671307
if (!session) {
12681308
zend_throw_error(NULL, "Invalid or uninitialized SNMP object");
1269-
efree(objid_query.vars);
1309+
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
12701310
RETURN_THROWS();
12711311
}
12721312

@@ -1292,7 +1332,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12921332

12931333
php_snmp_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, st, session, &objid_query);
12941334

1295-
efree(objid_query.vars);
1335+
php_free_objid_query(&objid_query, oid_ht, value_ht, st);
12961336

12971337
if (session_less_mode) {
12981338
netsnmp_session_free(&session);

ext/snmp/tests/gh16959.phpt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
--TEST--
2+
snmpget() modifies object_id array source
3+
--EXTENSIONS--
4+
snmp
5+
--SKIPIF--
6+
<?php
7+
require_once(__DIR__.'/skipif.inc');
8+
?>
9+
--FILE--
10+
<?php
11+
require_once(__DIR__.'/snmp_include.inc');
12+
13+
$bad_object_ids = array (
14+
077 => 077, -066 => -066, -0345 => -0345, 0 => 0
15+
);
16+
var_dump($bad_object_ids);
17+
var_dump(snmpget($hostname, "", $bad_object_ids) === false);
18+
// The array should remain unmodified
19+
var_dump($bad_object_ids);
20+
try {
21+
snmpget($hostname, "", [0 => new stdClass()]);
22+
} catch (Throwable $e) {
23+
echo $e->getMessage() . PHP_EOL;
24+
}
25+
26+
try {
27+
snmp2_set($hostname, $communityWrite, $bad_object_ids, array(new stdClass()), array(null));
28+
} catch (Throwable $e) {
29+
echo $e->getMessage() . PHP_EOL;
30+
}
31+
try {
32+
snmp2_set($hostname, $communityWrite, $bad_object_ids, array("toolongtype"), array(null));
33+
} catch (Throwable $e) {
34+
echo $e->getMessage() . PHP_EOL;
35+
}
36+
try {
37+
snmp2_set($hostname, $communityWrite, $bad_object_ids, array(str_repeat("onetoomuch", random_int(1, 1))), array(null));
38+
} catch (Throwable $e) {
39+
echo $e->getMessage();
40+
}
41+
?>
42+
--EXPECTF--
43+
array(4) {
44+
[63]=>
45+
int(63)
46+
[-54]=>
47+
int(-54)
48+
[-229]=>
49+
int(-229)
50+
[0]=>
51+
int(0)
52+
}
53+
54+
Warning: snmpget(): Invalid object identifier: -54 in %s on line %d
55+
bool(true)
56+
array(4) {
57+
[63]=>
58+
int(63)
59+
[-54]=>
60+
int(-54)
61+
[-229]=>
62+
int(-229)
63+
[0]=>
64+
int(0)
65+
}
66+
Object of class stdClass could not be converted to string
67+
Object of class stdClass could not be converted to string
68+
Type must be a single character
69+
Type must be a single character

0 commit comments

Comments
 (0)