@@ -626,6 +626,31 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st,
626626}
627627/* }}} */
628628
629+ static void php_snmp_zend_string_release_from_char_pointer (char * ptr ) {
630+ if (ptr ) {
631+ zend_string * pptr = (zend_string * )(ptr - XtOffsetOf (zend_string , val ));
632+ zend_string_release (pptr );
633+ }
634+ }
635+
636+ static void php_free_objid_query (struct objid_query * objid_query , HashTable * oid_ht , const HashTable * value_ht , int st ) {
637+ if (oid_ht ) {
638+ uint32_t count = zend_hash_num_elements (oid_ht );
639+
640+ for (uint32_t i = 0 ; i < count ; i ++ ) {
641+ snmpobjarg * arg = & objid_query -> vars [i ];
642+ if (!arg -> oid ) {
643+ break ;
644+ }
645+ if (value_ht ) {
646+ php_snmp_zend_string_release_from_char_pointer (arg -> value );
647+ }
648+ php_snmp_zend_string_release_from_char_pointer (arg -> oid );
649+ }
650+ }
651+ efree (objid_query -> vars );
652+ }
653+
629654/* {{{ php_snmp_parse_oid
630655*
631656* OID parser (and type, value for SNMP_SET command)
@@ -674,10 +699,15 @@ static bool php_snmp_parse_oid(
674699 return false;
675700 }
676701 objid_query -> vars = (snmpobjarg * )safe_emalloc (sizeof (snmpobjarg ), zend_hash_num_elements (oid_ht ), 0 );
702+ memset (objid_query -> vars , 0 , sizeof (snmpobjarg ) * zend_hash_num_elements (oid_ht ));
677703 objid_query -> array_output = (st & SNMP_CMD_SET ) == 0 ;
678704 ZEND_HASH_FOREACH_VAL (oid_ht , tmp_oid ) {
679- convert_to_string (tmp_oid );
680- objid_query -> vars [objid_query -> count ].oid = Z_STRVAL_P (tmp_oid );
705+ zend_string * tmp = zval_try_get_string (tmp_oid );
706+ if (!tmp ) {
707+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
708+ return false;
709+ }
710+ objid_query -> vars [objid_query -> count ].oid = ZSTR_VAL (tmp );
681711 if (st & SNMP_CMD_SET ) {
682712 if (type_str ) {
683713 pptr = ZSTR_VAL (type_str );
@@ -701,18 +731,24 @@ static bool php_snmp_parse_oid(
701731 }
702732 }
703733 if (idx_type < type_ht -> nNumUsed ) {
704- convert_to_string (tmp_type );
705- if (Z_STRLEN_P (tmp_type ) != 1 ) {
734+ zend_string * type = zval_try_get_string (tmp_type );
735+ if (!type ) {
736+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
737+ return false;
738+ }
739+ size_t len = ZSTR_LEN (type );
740+ char ptype = * ZSTR_VAL (type );
741+ zend_string_release (type );
742+ if (len != 1 ) {
706743 zend_value_error ("Type must be a single character" );
707- efree (objid_query -> vars );
744+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
708745 return false;
709746 }
710- pptr = Z_STRVAL_P (tmp_type );
711- objid_query -> vars [objid_query -> count ].type = * pptr ;
747+ objid_query -> vars [objid_query -> count ].type = ptype ;
712748 idx_type ++ ;
713749 } else {
714- php_error_docref (NULL , E_WARNING , "'%s': no type set" , Z_STRVAL_P ( tmp_oid ));
715- efree (objid_query -> vars );
750+ php_error_docref (NULL , E_WARNING , "'%s': no type set" , ZSTR_VAL ( tmp ));
751+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
716752 return false;
717753 }
718754 }
@@ -738,12 +774,16 @@ static bool php_snmp_parse_oid(
738774 }
739775 }
740776 if (idx_value < value_ht -> nNumUsed ) {
741- convert_to_string (tmp_value );
742- objid_query -> vars [objid_query -> count ].value = Z_STRVAL_P (tmp_value );
777+ zend_string * tmp = zval_try_get_string (tmp_value );
778+ if (!tmp ) {
779+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
780+ return false;
781+ }
782+ objid_query -> vars [objid_query -> count ].value = ZSTR_VAL (tmp );
743783 idx_value ++ ;
744784 } else {
745- php_error_docref (NULL , E_WARNING , "'%s': no value set" , Z_STRVAL_P ( tmp_oid ));
746- efree (objid_query -> vars );
785+ php_error_docref (NULL , E_WARNING , "'%s': no value set" , ZSTR_VAL ( tmp ));
786+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
747787 return false;
748788 }
749789 }
@@ -756,14 +796,14 @@ static bool php_snmp_parse_oid(
756796 if (st & SNMP_CMD_WALK ) {
757797 if (objid_query -> count > 1 ) {
758798 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Multi OID walks are not supported!" );
759- efree (objid_query -> vars );
799+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
760800 return false;
761801 }
762802 objid_query -> vars [0 ].name_length = MAX_NAME_LEN ;
763803 if (strlen (objid_query -> vars [0 ].oid )) { /* on a walk, an empty string means top of tree - no error */
764804 if (!snmp_parse_oid (objid_query -> vars [0 ].oid , objid_query -> vars [0 ].name , & (objid_query -> vars [0 ].name_length ))) {
765805 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Invalid object identifier: %s" , objid_query -> vars [0 ].oid );
766- efree (objid_query -> vars );
806+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
767807 return false;
768808 }
769809 } else {
@@ -775,7 +815,7 @@ static bool php_snmp_parse_oid(
775815 objid_query -> vars [objid_query -> offset ].name_length = MAX_OID_LEN ;
776816 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 ))) {
777817 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Invalid object identifier: %s" , objid_query -> vars [objid_query -> offset ].oid );
778- efree (objid_query -> vars );
818+ php_free_objid_query (objid_query , oid_ht , value_ht , st );
779819 return false;
780820 }
781821 }
@@ -1252,12 +1292,12 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12521292
12531293 if (session_less_mode ) {
12541294 if (!netsnmp_session_init (& session , version , a1 , a2 , timeout , retries )) {
1255- efree ( objid_query . vars );
1295+ php_free_objid_query ( & objid_query , oid_ht , value_ht , st );
12561296 netsnmp_session_free (& session );
12571297 RETURN_FALSE ;
12581298 }
12591299 if (version == SNMP_VERSION_3 && !netsnmp_session_set_security (session , a3 , a4 , a5 , a6 , a7 , NULL , NULL )) {
1260- efree ( objid_query . vars );
1300+ php_free_objid_query ( & objid_query , oid_ht , value_ht , st );
12611301 netsnmp_session_free (& session );
12621302 /* Warning message sent already, just bail out */
12631303 RETURN_FALSE ;
@@ -1268,7 +1308,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12681308 session = snmp_object -> session ;
12691309 if (!session ) {
12701310 zend_throw_error (NULL , "Invalid or uninitialized SNMP object" );
1271- efree ( objid_query . vars );
1311+ php_free_objid_query ( & objid_query , oid_ht , value_ht , st );
12721312 RETURN_THROWS ();
12731313 }
12741314
@@ -1294,7 +1334,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12941334
12951335 php_snmp_internal (INTERNAL_FUNCTION_PARAM_PASSTHRU , st , session , & objid_query );
12961336
1297- efree ( objid_query . vars );
1337+ php_free_objid_query ( & objid_query , oid_ht , value_ht , st );
12981338
12991339 if (session_less_mode ) {
13001340 netsnmp_session_free (& session );
0 commit comments