@@ -626,6 +626,40 @@ 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+ if (GC_REFCOUNT (pptr )) {
633+ zend_string_release (pptr );
634+ }
635+ }
636+ }
637+
638+ static void php_free_objid_query (struct objid_query * objid_query , HashTable * oid_ht , zend_string * value_str , HashTable * value_ht , int st ) {
639+ #define PHP_FREE_OBJID_VAL (arg ) \
640+ do { \
641+ if (value_ht && !value_str) { \
642+ php_snmp_zend_string_release_from_char_pointer(arg->value); \
643+ } \
644+ php_snmp_zend_string_release_from_char_pointer(&arg->type); \
645+ php_snmp_zend_string_release_from_char_pointer(arg->oid); \
646+ } while (0)
647+
648+ if (oid_ht ) {
649+ uint32_t i = 0 , count = zend_hash_num_elements (oid_ht );
650+
651+ while (i < count ) {
652+ snmpobjarg * arg = & objid_query -> vars [i ];
653+ if (!arg -> oid ) {
654+ break ;
655+ }
656+ PHP_FREE_OBJID_VAL (arg );
657+ i ++ ;
658+ }
659+ }
660+ efree (objid_query -> vars );
661+ }
662+
629663/* {{{ php_snmp_parse_oid
630664*
631665* OID parser (and type, value for SNMP_SET command)
@@ -674,15 +708,15 @@ static bool php_snmp_parse_oid(
674708 return false;
675709 }
676710 objid_query -> vars = (snmpobjarg * )safe_emalloc (sizeof (snmpobjarg ), zend_hash_num_elements (oid_ht ), 0 );
711+ memset (objid_query -> vars , 0 , sizeof (snmpobjarg ) * zend_hash_num_elements (oid_ht ));
677712 objid_query -> array_output = (st & SNMP_CMD_SET ) == 0 ;
678713 ZEND_HASH_FOREACH_VAL (oid_ht , tmp_oid ) {
679714 zend_string * tmp = zval_try_get_string (tmp_oid );
680715 if (!tmp ) {
681- efree (objid_query -> vars );
716+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
682717 return false;
683718 }
684719 objid_query -> vars [objid_query -> count ].oid = ZSTR_VAL (tmp );
685- zend_string_release (tmp );
686720 if (st & SNMP_CMD_SET ) {
687721 if (type_str ) {
688722 pptr = ZSTR_VAL (type_str );
@@ -706,18 +740,23 @@ static bool php_snmp_parse_oid(
706740 }
707741 }
708742 if (idx_type < type_ht -> nNumUsed ) {
709- convert_to_string (tmp_type );
710- if (Z_STRLEN_P (tmp_type ) != 1 ) {
743+ zend_string * type = zval_try_get_string (tmp_type );
744+ if (!type ) {
745+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
746+ return false;
747+ }
748+ if (ZSTR_LEN (type ) != 1 ) {
711749 zend_value_error ("Type must be a single character" );
712- efree (objid_query -> vars );
750+ zend_string_release (type );
751+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
713752 return false;
714753 }
715- pptr = Z_STRVAL_P ( tmp_type );
754+ pptr = ZSTR_VAL ( type );
716755 objid_query -> vars [objid_query -> count ].type = * pptr ;
717756 idx_type ++ ;
718757 } else {
719- php_error_docref (NULL , E_WARNING , "'%s': no type set" , Z_STRVAL_P ( tmp_oid ));
720- efree (objid_query -> vars );
758+ php_error_docref (NULL , E_WARNING , "'%s': no type set" , ZSTR_VAL ( tmp ));
759+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
721760 return false;
722761 }
723762 }
@@ -743,12 +782,16 @@ static bool php_snmp_parse_oid(
743782 }
744783 }
745784 if (idx_value < value_ht -> nNumUsed ) {
746- convert_to_string (tmp_value );
747- objid_query -> vars [objid_query -> count ].value = Z_STRVAL_P (tmp_value );
785+ zend_string * tmp = zval_try_get_string (tmp_value );
786+ if (!tmp ) {
787+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
788+ return false;
789+ }
790+ objid_query -> vars [objid_query -> count ].value = ZSTR_VAL (tmp );
748791 idx_value ++ ;
749792 } else {
750- php_error_docref (NULL , E_WARNING , "'%s': no value set" , Z_STRVAL_P ( tmp_oid ));
751- efree (objid_query -> vars );
793+ php_error_docref (NULL , E_WARNING , "'%s': no value set" , ZSTR_VAL ( tmp ));
794+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
752795 return false;
753796 }
754797 }
@@ -761,14 +804,14 @@ static bool php_snmp_parse_oid(
761804 if (st & SNMP_CMD_WALK ) {
762805 if (objid_query -> count > 1 ) {
763806 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Multi OID walks are not supported!" );
764- efree (objid_query -> vars );
807+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
765808 return false;
766809 }
767810 objid_query -> vars [0 ].name_length = MAX_NAME_LEN ;
768811 if (strlen (objid_query -> vars [0 ].oid )) { /* on a walk, an empty string means top of tree - no error */
769812 if (!snmp_parse_oid (objid_query -> vars [0 ].oid , objid_query -> vars [0 ].name , & (objid_query -> vars [0 ].name_length ))) {
770813 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Invalid object identifier: %s" , objid_query -> vars [0 ].oid );
771- efree (objid_query -> vars );
814+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
772815 return false;
773816 }
774817 } else {
@@ -780,7 +823,7 @@ static bool php_snmp_parse_oid(
780823 objid_query -> vars [objid_query -> offset ].name_length = MAX_OID_LEN ;
781824 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 ))) {
782825 php_snmp_error (object , PHP_SNMP_ERRNO_OID_PARSING_ERROR , "Invalid object identifier: %s" , objid_query -> vars [objid_query -> offset ].oid );
783- efree (objid_query -> vars );
826+ php_free_objid_query (objid_query , oid_ht , value_str , value_ht , st );
784827 return false;
785828 }
786829 }
@@ -1257,12 +1300,12 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12571300
12581301 if (session_less_mode ) {
12591302 if (!netsnmp_session_init (& session , version , a1 , a2 , timeout , retries )) {
1260- efree ( objid_query . vars );
1303+ php_free_objid_query ( & objid_query , oid_ht , value_str , value_ht , st );
12611304 netsnmp_session_free (& session );
12621305 RETURN_FALSE ;
12631306 }
12641307 if (version == SNMP_VERSION_3 && !netsnmp_session_set_security (session , a3 , a4 , a5 , a6 , a7 , NULL , NULL )) {
1265- efree ( objid_query . vars );
1308+ php_free_objid_query ( & objid_query , oid_ht , value_str , value_ht , st );
12661309 netsnmp_session_free (& session );
12671310 /* Warning message sent already, just bail out */
12681311 RETURN_FALSE ;
@@ -1273,7 +1316,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12731316 session = snmp_object -> session ;
12741317 if (!session ) {
12751318 zend_throw_error (NULL , "Invalid or uninitialized SNMP object" );
1276- efree ( objid_query . vars );
1319+ php_free_objid_query ( & objid_query , oid_ht , value_str , value_ht , st );
12771320 RETURN_THROWS ();
12781321 }
12791322
@@ -1299,7 +1342,7 @@ static void php_snmp(INTERNAL_FUNCTION_PARAMETERS, int st, int version)
12991342
13001343 php_snmp_internal (INTERNAL_FUNCTION_PARAM_PASSTHRU , st , session , & objid_query );
13011344
1302- efree ( objid_query . vars );
1345+ php_free_objid_query ( & objid_query , oid_ht , value_str , value_ht , st );
13031346
13041347 if (session_less_mode ) {
13051348 netsnmp_session_free (& session );
0 commit comments