Skip to content

Commit efe6d96

Browse files
ptomulikCôme Chilliet
authored and
Côme Chilliet
committed
fix memory leaks in ext/ldap/ldap.c
1 parent 1aeff52 commit efe6d96

File tree

2 files changed

+101
-104
lines changed

2 files changed

+101
-104
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ PHP NEWS
66
. Fixed bug #79884 (PHP_CONFIG_FILE_PATH is meaningless). (cmb)
77
. Fixed bug #77932 (File extensions are case-sensitive). (cmb)
88

9+
- LDAP:
10+
. Fixed memory leaks. (ptomulik)
11+
912
?? ??? ????, PHP 7.3.21
1013

1114
- Apache:

ext/ldap/ldap.c

Lines changed: 98 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,17 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
167167
}
168168
} else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
169169
int lestimated, rc;
170-
struct berval lcookie;
170+
struct berval lcookie = { 0L, NULL };
171171
zval value;
172172

173173
if (ctrl->ldctl_value.bv_len) {
174+
/* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
174175
rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
175176
} else {
176177
/* ldap_parse_pageresponse_control will crash if value is empty */
177178
rc = -1;
178179
}
180+
179181
if ( rc == LDAP_SUCCESS ) {
180182
array_init(&value);
181183
add_assoc_long(&value, "size", lestimated);
@@ -184,6 +186,10 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
184186
} else {
185187
add_assoc_null(array, "value");
186188
}
189+
190+
if (lcookie.bv_val) {
191+
ldap_memfree(lcookie.bv_val);
192+
}
187193
} else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
188194
BerElement *ber;
189195
struct berval bv;
@@ -302,27 +308,23 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
302308
control_iscritical = 0;
303309
}
304310

305-
struct berval *control_value = NULL;
311+
BerElement *ber = NULL;
312+
struct berval control_value = { 0L, NULL };
313+
int control_value_alloc = 0;
306314

307315
if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) {
308316
if (Z_TYPE_P(val) != IS_ARRAY) {
309-
control_value = ber_memalloc(sizeof * control_value);
310-
if (control_value == NULL) {
317+
tmpstring = zval_get_string(val);
318+
if (EG(exception)) {
311319
rc = -1;
312-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
313-
} else {
314-
tmpstring = zval_get_string(val);
315-
if (EG(exception)) {
316-
rc = -1;
317-
goto failure;
318-
}
319-
control_value->bv_val = ZSTR_VAL(tmpstring);
320-
control_value->bv_len = ZSTR_LEN(tmpstring);
320+
goto failure;
321321
}
322+
control_value.bv_val = ZSTR_VAL(tmpstring);
323+
control_value.bv_len = ZSTR_LEN(tmpstring);
322324
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
323325
zval* tmp;
324326
int pagesize = 1;
325-
struct berval cookie = { 0, NULL };
327+
struct berval cookie = { 0L, NULL };
326328
if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
327329
pagesize = zval_get_long(tmp);
328330
}
@@ -335,15 +337,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
335337
cookie.bv_val = ZSTR_VAL(tmpstring);
336338
cookie.bv_len = ZSTR_LEN(tmpstring);
337339
}
338-
control_value = ber_memalloc(sizeof * control_value);
339-
if (control_value == NULL) {
340-
rc = -1;
341-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
342-
} else {
343-
rc = ldap_create_page_control_value(ld, pagesize, &cookie, control_value);
344-
if (rc != LDAP_SUCCESS) {
345-
php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
346-
}
340+
/* ldap_create_page_control_value() allocates memory for control_value.bv_val */
341+
control_value_alloc = 1;
342+
rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
343+
if (rc != LDAP_SUCCESS) {
344+
php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
347345
}
348346
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
349347
zval* tmp;
@@ -357,19 +355,15 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
357355
rc = -1;
358356
goto failure;
359357
}
360-
control_value = ber_memalloc(sizeof * control_value);
361-
if (control_value == NULL) {
362-
rc = -1;
363-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
364-
} else {
365-
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
366-
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
367-
int success = LDAP_SUCCESS;
368-
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
369-
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), control_value);
370-
if (rc != LDAP_SUCCESS) {
371-
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
372-
}
358+
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
359+
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
360+
int success = LDAP_SUCCESS;
361+
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
362+
/* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
363+
control_value_alloc = 1;
364+
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
365+
if (rc != LDAP_SUCCESS) {
366+
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
373367
}
374368
zend_string_release(assert);
375369
}
@@ -379,9 +373,8 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
379373
rc = -1;
380374
php_error_docref(NULL, E_WARNING, "Filter missing from control value array");
381375
} else {
382-
BerElement *vrber = ber_alloc_t(LBER_USE_DER);
383-
control_value = ber_memalloc(sizeof * control_value);
384-
if ((control_value == NULL) || (vrber == NULL)) {
376+
ber = ber_alloc_t(LBER_USE_DER);
377+
if (ber == NULL) {
385378
rc = -1;
386379
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
387380
} else {
@@ -390,14 +383,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
390383
rc = -1;
391384
goto failure;
392385
}
393-
if (ldap_put_vrFilter(vrber, ZSTR_VAL(tmpstring)) == -1) {
394-
ber_free(vrber, 1);
386+
if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
395387
rc = -1;
396388
php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
397-
} else {
398-
if (ber_flatten2(vrber, control_value, 0) == -1) {
399-
rc = -1;
400-
}
389+
} else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
390+
rc = -1;
401391
}
402392
}
403393
}
@@ -407,10 +397,9 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
407397
rc = -1;
408398
php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array");
409399
} else {
410-
BerElement *ber = ber_alloc_t(LBER_USE_DER);
400+
ber = ber_alloc_t(LBER_USE_DER);
411401

412-
control_value = ber_memalloc(sizeof * control_value);
413-
if ((control_value == NULL) || (ber == NULL)) {
402+
if (ber == NULL) {
414403
rc = -1;
415404
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
416405
} else {
@@ -446,7 +435,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
446435
php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
447436
} else {
448437
int err;
449-
err = ber_flatten2(ber, control_value, 0);
438+
err = ber_flatten2(ber, &control_value, control_value_alloc);
450439
if (err < 0) {
451440
rc = -1;
452441
php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
@@ -505,15 +494,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
505494
}
506495
}
507496
sort_keys[num_keys] = NULL;
508-
control_value = ber_memalloc(sizeof * control_value);
509-
if (control_value == NULL) {
510-
rc = -1;
511-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
512-
} else {
513-
rc = ldap_create_sort_control_value(ld, sort_keys, control_value);
514-
if (rc != LDAP_SUCCESS) {
515-
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
516-
}
497+
/* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
498+
control_value_alloc = 1;
499+
rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
500+
if (rc != LDAP_SUCCESS) {
501+
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
517502
}
518503
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
519504
zval* tmp;
@@ -575,15 +560,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
575560
vlvInfo.ldvlv_context = NULL;
576561
}
577562

578-
control_value = ber_memalloc(sizeof * control_value);
579-
if (control_value == NULL) {
580-
rc = -1;
581-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
582-
} else {
583-
rc = ldap_create_vlv_control_value(ld, &vlvInfo, control_value);
584-
if (rc != LDAP_SUCCESS) {
585-
php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
586-
}
563+
/* ldap_create_vlv_control_value() allocates memory for control_value.bv_val */
564+
control_value_alloc = 1;
565+
rc = ldap_create_vlv_control_value(ld, &vlvInfo, &control_value);
566+
if (rc != LDAP_SUCCESS) {
567+
php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
587568
}
588569
} else {
589570
php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", ZSTR_VAL(control_oid));
@@ -592,7 +573,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
592573
}
593574

594575
if (rc == LDAP_SUCCESS) {
595-
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, control_value, 1, ctrl);
576+
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
596577
}
597578

598579
failure:
@@ -614,9 +595,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
614595
}
615596
efree(tmpstrings2);
616597
}
617-
if (control_value != NULL) {
618-
ber_memfree(control_value);
619-
control_value = NULL;
598+
if (control_value.bv_val != NULL && control_value_alloc != 0) {
599+
ber_memfree(control_value.bv_val);
600+
}
601+
if (ber != NULL) {
602+
ber_free(ber, 1);
620603
}
621604
if (ldap_attrs != NULL) {
622605
efree(ldap_attrs);
@@ -1488,7 +1471,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
14881471
zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
14891472
char **ldap_attrs = NULL;
14901473
ldap_linkdata *ld = NULL;
1491-
LDAPMessage *ldap_res;
1474+
LDAPMessage *ldap_res = NULL;
14921475
LDAPControl **lserverctrls = NULL;
14931476
int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
14941477
int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
@@ -1688,6 +1671,11 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
16881671
&& errno != LDAP_REFERRAL
16891672
#endif
16901673
) {
1674+
/* ldap_res should be freed regardless of return value of ldap_search_ext_s()
1675+
* see: https://linux.die.net/man/3/ldap_search_ext_s */
1676+
if (ldap_res != NULL) {
1677+
ldap_msgfree(ldap_res);
1678+
}
16911679
php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(errno));
16921680
ret = 0;
16931681
} else {
@@ -4016,7 +4004,7 @@ PHP_FUNCTION(ldap_control_paged_result)
40164004
zval *link;
40174005
char *cookie = NULL;
40184006
size_t cookie_len = 0;
4019-
struct berval lcookie = { 0, NULL };
4007+
struct berval lcookie = { 0L, NULL };
40204008
ldap_linkdata *ld;
40214009
LDAP *ldap;
40224010
BerElement *ber = NULL;
@@ -4311,38 +4299,31 @@ PHP_FUNCTION(ldap_exop)
43114299
PHP_FUNCTION(ldap_exop_passwd)
43124300
{
43134301
zval *link, *serverctrls;
4314-
struct berval luser, loldpw, lnewpw, lgenpasswd;
4315-
LDAPControl **lserverctrls = NULL, **requestctrls = NULL;
4316-
LDAPControl *ctrl, **ctrlp;
4317-
LDAPMessage* ldap_res;
4302+
struct berval luser = { 0L, NULL };
4303+
struct berval loldpw = { 0L, NULL };
4304+
struct berval lnewpw = { 0L, NULL };
4305+
struct berval lgenpasswd = { 0L, NULL };
4306+
LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
4307+
LDAPMessage* ldap_res = NULL;
43184308
ldap_linkdata *ld;
43194309
int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
4320-
char* errmsg;
4321-
4322-
luser.bv_len = 0;
4323-
loldpw.bv_len = 0;
4324-
lnewpw.bv_len = 0;
4310+
char* errmsg = NULL;
43254311

43264312
if (zend_parse_parameters(myargcount, "r|sssz/", &link, &luser.bv_val, &luser.bv_len, &loldpw.bv_val, &loldpw.bv_len, &lnewpw.bv_val, &lnewpw.bv_len, &serverctrls) == FAILURE) {
43274313
return;
43284314
}
43294315

43304316
if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4331-
RETURN_FALSE;
4317+
RETVAL_FALSE;
4318+
goto cleanup;
43324319
}
43334320

43344321
switch (myargcount) {
43354322
case 5:
4336-
requestctrls = safe_emalloc(2, sizeof(*requestctrls), 0);
4337-
*requestctrls = NULL;
4338-
ctrlp = requestctrls;
4339-
4323+
/* ldap_create_passwordpolicy_control() allocates ctrl */
43404324
if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
4341-
*ctrlp = ctrl;
4342-
++ctrlp;
4325+
requestctrls[0] = ctrl;
43434326
}
4344-
4345-
*ctrlp = NULL;
43464327
}
43474328

43484329
/* asynchronous call to get result and controls */
@@ -4352,35 +4333,44 @@ PHP_FUNCTION(ldap_exop_passwd)
43524333
requestctrls,
43534334
NULL, &msgid);
43544335

4355-
if (requestctrls != NULL) {
4356-
efree(requestctrls);
4336+
if (requestctrls[0] != NULL) {
4337+
ldap_control_free(requestctrls[0]);
43574338
}
43584339

43594340
if (rc != LDAP_SUCCESS ) {
43604341
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4361-
RETURN_FALSE;
4342+
RETVAL_FALSE;
4343+
goto cleanup;
43624344
}
43634345

43644346
rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
43654347
if ((rc < 0) || !ldap_res) {
43664348
rc = _get_lderrno(ld->link);
43674349
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4368-
RETURN_FALSE;
4350+
RETVAL_FALSE;
4351+
goto cleanup;
43694352
}
43704353

43714354
rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
43724355
if( rc != LDAP_SUCCESS ) {
43734356
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4374-
ldap_msgfree(ldap_res);
4375-
RETURN_FALSE;
4357+
RETVAL_FALSE;
4358+
goto cleanup;
43764359
}
43774360

4378-
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 1);
4361+
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
43794362
if( rc != LDAP_SUCCESS ) {
43804363
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4381-
RETURN_FALSE;
4364+
RETVAL_FALSE;
4365+
goto cleanup;
4366+
}
4367+
4368+
if (myargcount > 4) {
4369+
zval_ptr_dtor(serverctrls);
4370+
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
43824371
}
43834372

4373+
/* return */
43844374
if (lnewpw.bv_len == 0) {
43854375
if (lgenpasswd.bv_len == 0) {
43864376
RETVAL_EMPTY_STRING();
@@ -4394,12 +4384,16 @@ PHP_FUNCTION(ldap_exop_passwd)
43944384
RETVAL_FALSE;
43954385
}
43964386

4397-
if (myargcount > 4) {
4398-
zval_ptr_dtor(serverctrls);
4399-
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
4387+
cleanup:
4388+
if (lgenpasswd.bv_val != NULL) {
4389+
ldap_memfree(lgenpasswd.bv_val);
4390+
}
4391+
if (ldap_res != NULL) {
4392+
ldap_msgfree(ldap_res);
4393+
}
4394+
if (errmsg != NULL) {
4395+
ldap_memfree(errmsg);
44004396
}
4401-
4402-
ldap_memfree(lgenpasswd.bv_val);
44034397
}
44044398
/* }}} */
44054399
#endif

0 commit comments

Comments
 (0)