@@ -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 );
0 commit comments