Fix some leaks in ldap
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 14 Jun 2019 09:11:24 +0000 (11:11 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 14 Jun 2019 09:11:24 +0000 (11:11 +0200)
The result of zval_get_string() needs to be released. In some places
where it is inconvenient to manage, I went back to convert_to_string.
It is safe in those places due to existing array separations.

Also fix a preexisting leak when getting controls, the previous
value was not destroyed.

ext/ldap/ldap.c

index f68f0bded0a3da7eda42a0b3bcc21c503691a7ab..a348b6e7b1e778cc5bb27e5eef2beea6a2df4fb6 100644 (file)
@@ -279,7 +279,7 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
 static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array)
 {
        zval* val;
-       zend_string *control_oid = NULL;
+       zend_string *control_oid;
        int control_iscritical = 0, rc = LDAP_SUCCESS;
        char** ldap_attrs = NULL;
        LDAPSortKey** sort_keys = NULL;
@@ -312,7 +312,8 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
                        } else {
                                tmpstring = zval_get_string(val);
                                if (EG(exception)) {
-                                       return -1;
+                                       rc = -1;
+                                       goto failure;
                                }
                                control_value->bv_val = ZSTR_VAL(tmpstring);
                                control_value->bv_len = ZSTR_LEN(tmpstring);
@@ -369,6 +370,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
                                                php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
                                        }
                                }
+                               zend_string_release(assert);
                        }
                } else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VALUESRETURNFILTER) == 0) {
                        zval* tmp;
@@ -585,6 +587,10 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
        }
 
 failure:
+       zend_string_release(control_oid);
+       if (tmpstring != NULL) {
+               zend_string_release(tmpstring);
+       }
        if (control_value != NULL) {
                ber_memfree(control_value);
                control_value = NULL;
@@ -1456,7 +1462,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
 {
        zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls = NULL;
        zend_long attrsonly, sizelimit, timelimit, deref;
-       zend_string *ldap_filter = NULL, *ldap_base_dn = NULL, *tmpstring;
+       zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
        char **ldap_attrs = NULL;
        ldap_linkdata *ld = NULL;
        LDAPMessage *ldap_res;
@@ -1465,7 +1471,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
        int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
        int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS();
 
-       if (zend_parse_parameters(argcount, "zzz|alllla", &link, &base_dn, &filter, &attrs, &attrsonly,
+       if (zend_parse_parameters(argcount, "zzz|alllla/", &link, &base_dn, &filter, &attrs, &attrsonly,
                &sizelimit, &timelimit, &deref, &serverctrls) == FAILURE) {
                return;
        }
@@ -1492,12 +1498,12 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
                                        goto cleanup;
                                }
 
-                               tmpstring = zval_get_string(attr);
+                               convert_to_string(attr);
                                if (EG(exception)) {
                                        ret = 0;
                                        goto cleanup;
                                }
-                               ldap_attrs[i] = ZSTR_VAL(tmpstring);
+                               ldap_attrs[i] = Z_STRVAL_P(attr);
                        }
                        ldap_attrs[num_attribs] = NULL;
                default:
@@ -1680,6 +1686,12 @@ cleanup:
                /* Restoring previous options */
                php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
        }
+       if (ldap_filter) {
+               zend_string_release(ldap_filter);
+       }
+       if (ldap_base_dn) {
+               zend_string_release(ldap_base_dn);
+       }
        if (ldap_attrs != NULL) {
                efree(ldap_attrs);
        }
@@ -2213,7 +2225,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
        int i, j, num_attribs, num_values, msgid;
        size_t dn_len;
        int *num_berval;
-       zend_string *attribute, *tmpstring;
+       zend_string *attribute;
        zend_ulong index;
        int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
 
@@ -2274,14 +2286,14 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
 
 /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
                if ((num_values == 1) && (Z_TYPE_P(value) != IS_ARRAY)) {
-                       tmpstring = zval_get_string(value);
+                       convert_to_string(value);
                        if (EG(exception)) {
                                RETVAL_FALSE;
                                goto cleanup;
                        }
                        ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
-                       ldap_mods[i]->mod_bvalues[0]->bv_val = ZSTR_VAL(tmpstring);
-                       ldap_mods[i]->mod_bvalues[0]->bv_len = ZSTR_LEN(tmpstring);
+                       ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_P(value);
+                       ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_P(value);
                } else {
                        for (j = 0; j < num_values; j++) {
                                if ((ivalue = zend_hash_index_find(Z_ARRVAL_P(value), j)) == NULL) {
@@ -2291,14 +2303,14 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext)
                                        RETVAL_FALSE;
                                        goto cleanup;
                                }
-                               tmpstring = zval_get_string(ivalue);
+                               convert_to_string(ivalue);
                                if (EG(exception)) {
                                        RETVAL_FALSE;
                                        goto cleanup;
                                }
                                ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
-                               ldap_mods[i]->mod_bvalues[j]->bv_val = ZSTR_VAL(tmpstring);
-                               ldap_mods[i]->mod_bvalues[j]->bv_len = ZSTR_LEN(tmpstring);
+                               ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_P(ivalue);
+                               ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(ivalue);
                        }
                }
                ldap_mods[i]->mod_bvalues[num_values] = NULL;
@@ -2823,6 +2835,7 @@ PHP_FUNCTION(ldap_modify_batch)
                                /* fill it */
                                ldap_mods[i]->mod_bvalues[j]->bv_len = ZSTR_LEN(modval);
                                ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(ZSTR_VAL(modval), ZSTR_LEN(modval));
+                               zend_string_release(modval);
                        }
 
                        /* NULL-terminate values */
@@ -3187,6 +3200,7 @@ PHP_FUNCTION(ldap_get_option)
                                }
                                RETURN_FALSE;
                        }
+                       zval_ptr_dtor(retval);
                        _php_ldap_controls_to_array(ld->link, ctrls, retval, 1);
                } break;
 /* options not implemented
@@ -3331,8 +3345,10 @@ PHP_FUNCTION(ldap_set_option)
                                RETURN_FALSE;
                        }
                        if (ldap_set_option(ldap, option, ZSTR_VAL(val))) {
+                               zend_string_release(val);
                                RETURN_FALSE;
                        }
+                       zend_string_release(val);
                } break;
                /* options with boolean value */
        case LDAP_OPT_REFERRALS: