Skip to content

Commit fef5a9e

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

File tree

1 file changed

+97
-103
lines changed

1 file changed

+97
-103
lines changed

ext/ldap/ldap.c

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

172172
if (ctrl->ldctl_value.bv_len) {
173+
/* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
173174
rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
174175
} else {
175176
/* ldap_parse_pageresponse_control will crash if value is empty */
176177
rc = -1;
177178
}
179+
178180
if ( rc == LDAP_SUCCESS ) {
179181
array_init(&value);
180182
add_assoc_long(&value, "size", lestimated);
@@ -183,6 +185,10 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
183185
} else {
184186
add_assoc_null(array, "value");
185187
}
188+
189+
if (lcookie.bv_val) {
190+
ldap_memfree(lcookie.bv_val);
191+
}
186192
} else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
187193
BerElement *ber;
188194
struct berval bv;
@@ -301,27 +307,23 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
301307
control_iscritical = 0;
302308
}
303309

304-
struct berval *control_value = NULL;
310+
BerElement *ber = NULL;
311+
struct berval control_value = { 0L, NULL };
312+
int control_value_alloc = 0;
305313

306314
if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) {
307315
if (Z_TYPE_P(val) != IS_ARRAY) {
308-
control_value = ber_memalloc(sizeof * control_value);
309-
if (control_value == NULL) {
316+
tmpstring = zval_get_string(val);
317+
if (EG(exception)) {
310318
rc = -1;
311-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
312-
} else {
313-
tmpstring = zval_get_string(val);
314-
if (EG(exception)) {
315-
rc = -1;
316-
goto failure;
317-
}
318-
control_value->bv_val = ZSTR_VAL(tmpstring);
319-
control_value->bv_len = ZSTR_LEN(tmpstring);
319+
goto failure;
320320
}
321+
control_value.bv_val = ZSTR_VAL(tmpstring);
322+
control_value.bv_len = ZSTR_LEN(tmpstring);
321323
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
322324
zval* tmp;
323325
int pagesize = 1;
324-
struct berval cookie = { 0, NULL };
326+
struct berval cookie = { 0L, NULL };
325327
if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
326328
pagesize = zval_get_long(tmp);
327329
}
@@ -334,15 +336,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
334336
cookie.bv_val = ZSTR_VAL(tmpstring);
335337
cookie.bv_len = ZSTR_LEN(tmpstring);
336338
}
337-
control_value = ber_memalloc(sizeof * control_value);
338-
if (control_value == NULL) {
339-
rc = -1;
340-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
341-
} else {
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);
345-
}
339+
/* ldap_create_page_control_value() allocates memory for control_value.bv_val */
340+
control_value_alloc = 1;
341+
rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
342+
if (rc != LDAP_SUCCESS) {
343+
php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
346344
}
347345
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
348346
zval* tmp;
@@ -356,19 +354,15 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
356354
rc = -1;
357355
goto failure;
358356
}
359-
control_value = ber_memalloc(sizeof * control_value);
360-
if (control_value == NULL) {
361-
rc = -1;
362-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
363-
} else {
364-
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
365-
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
366-
int success = LDAP_SUCCESS;
367-
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
368-
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), control_value);
369-
if (rc != LDAP_SUCCESS) {
370-
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
371-
}
357+
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
358+
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
359+
int success = LDAP_SUCCESS;
360+
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
361+
/* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
362+
control_value_alloc = 1;
363+
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
364+
if (rc != LDAP_SUCCESS) {
365+
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
372366
}
373367
zend_string_release(assert);
374368
}
@@ -378,9 +372,8 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
378372
rc = -1;
379373
php_error_docref(NULL, E_WARNING, "Filter missing from control value array");
380374
} else {
381-
BerElement *vrber = ber_alloc_t(LBER_USE_DER);
382-
control_value = ber_memalloc(sizeof * control_value);
383-
if ((control_value == NULL) || (vrber == NULL)) {
375+
ber = ber_alloc_t(LBER_USE_DER);
376+
if (ber == NULL) {
384377
rc = -1;
385378
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
386379
} else {
@@ -389,14 +382,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
389382
rc = -1;
390383
goto failure;
391384
}
392-
if (ldap_put_vrFilter(vrber, ZSTR_VAL(tmpstring)) == -1) {
393-
ber_free(vrber, 1);
385+
if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
394386
rc = -1;
395387
php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
396-
} else {
397-
if (ber_flatten2(vrber, control_value, 0) == -1) {
398-
rc = -1;
399-
}
388+
} else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
389+
rc = -1;
400390
}
401391
}
402392
}
@@ -406,10 +396,9 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
406396
rc = -1;
407397
php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array");
408398
} else {
409-
BerElement *ber = ber_alloc_t(LBER_USE_DER);
399+
ber = ber_alloc_t(LBER_USE_DER);
410400

411-
control_value = ber_memalloc(sizeof * control_value);
412-
if ((control_value == NULL) || (ber == NULL)) {
401+
if (ber == NULL) {
413402
rc = -1;
414403
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
415404
} else {
@@ -445,7 +434,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
445434
php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
446435
} else {
447436
int err;
448-
err = ber_flatten2(ber, control_value, 0);
437+
err = ber_flatten2(ber, &control_value, control_value_alloc);
449438
if (err < 0) {
450439
rc = -1;
451440
php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
@@ -504,15 +493,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
504493
}
505494
}
506495
sort_keys[num_keys] = NULL;
507-
control_value = ber_memalloc(sizeof * control_value);
508-
if (control_value == NULL) {
509-
rc = -1;
510-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
511-
} else {
512-
rc = ldap_create_sort_control_value(ld, sort_keys, control_value);
513-
if (rc != LDAP_SUCCESS) {
514-
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
515-
}
496+
/* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
497+
control_value_alloc = 1;
498+
rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
499+
if (rc != LDAP_SUCCESS) {
500+
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
516501
}
517502
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
518503
zval* tmp;
@@ -574,15 +559,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
574559
vlvInfo.ldvlv_context = NULL;
575560
}
576561

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

593574
if (rc == LDAP_SUCCESS) {
594-
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, control_value, 1, ctrl);
575+
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
595576
}
596577

597578
failure:
@@ -613,9 +594,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
613594
}
614595
efree(tmpstrings2);
615596
}
616-
if (control_value != NULL) {
617-
ber_memfree(control_value);
618-
control_value = NULL;
597+
if (control_value.bv_val != NULL && control_value_alloc != 0) {
598+
ber_memfree(control_value.bv_val);
599+
}
600+
if (ber != NULL) {
601+
ber_free(ber, 1);
619602
}
620603
if (ldap_attrs != NULL) {
621604
efree(ldap_attrs);
@@ -1463,7 +1446,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
14631446
zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
14641447
char **ldap_attrs = NULL;
14651448
ldap_linkdata *ld = NULL;
1466-
LDAPMessage *ldap_res;
1449+
LDAPMessage *ldap_res = NULL;
14671450
LDAPControl **lserverctrls = NULL;
14681451
int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
14691452
int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
@@ -1663,6 +1646,11 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
16631646
&& errno != LDAP_REFERRAL
16641647
#endif
16651648
) {
1649+
/* ldap_res should be freed regardless of return value of ldap_search_ext_s()
1650+
* see: https://linux.die.net/man/3/ldap_search_ext_s */
1651+
if (ldap_res != NULL) {
1652+
ldap_msgfree(ldap_res);
1653+
}
16661654
php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(errno));
16671655
ret = 0;
16681656
} else {
@@ -3984,7 +3972,7 @@ PHP_FUNCTION(ldap_control_paged_result)
39843972
zval *link;
39853973
char *cookie = NULL;
39863974
size_t cookie_len = 0;
3987-
struct berval lcookie = { 0, NULL };
3975+
struct berval lcookie = { 0L, NULL };
39883976
ldap_linkdata *ld;
39893977
LDAP *ldap;
39903978
BerElement *ber = NULL;
@@ -4275,38 +4263,31 @@ PHP_FUNCTION(ldap_exop)
42754263
PHP_FUNCTION(ldap_exop_passwd)
42764264
{
42774265
zval *link, *serverctrls;
4278-
struct berval luser, loldpw, lnewpw, lgenpasswd;
4279-
LDAPControl **lserverctrls = NULL, **requestctrls = NULL;
4280-
LDAPControl *ctrl, **ctrlp;
4281-
LDAPMessage* ldap_res;
4266+
struct berval luser = { 0L, NULL };
4267+
struct berval loldpw = { 0L, NULL };
4268+
struct berval lnewpw = { 0L, NULL };
4269+
struct berval lgenpasswd = { 0L, NULL };
4270+
LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
4271+
LDAPMessage* ldap_res = NULL;
42824272
ldap_linkdata *ld;
42834273
int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
4284-
char* errmsg;
4285-
4286-
luser.bv_len = 0;
4287-
loldpw.bv_len = 0;
4288-
lnewpw.bv_len = 0;
4274+
char* errmsg = NULL;
42894275

42904276
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) {
42914277
return;
42924278
}
42934279

42944280
if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
4295-
RETURN_FALSE;
4281+
RETVAL_FALSE;
4282+
goto cleanup;
42964283
}
42974284

42984285
switch (myargcount) {
42994286
case 5:
4300-
requestctrls = safe_emalloc(2, sizeof(*requestctrls), 0);
4301-
*requestctrls = NULL;
4302-
ctrlp = requestctrls;
4303-
4287+
/* ldap_create_passwordpolicy_control() allocates ctrl */
43044288
if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
4305-
*ctrlp = ctrl;
4306-
++ctrlp;
4289+
requestctrls[0] = ctrl;
43074290
}
4308-
4309-
*ctrlp = NULL;
43104291
}
43114292

43124293
/* asynchronous call to get result and controls */
@@ -4316,35 +4297,43 @@ PHP_FUNCTION(ldap_exop_passwd)
43164297
requestctrls,
43174298
NULL, &msgid);
43184299

4319-
if (requestctrls != NULL) {
4320-
efree(requestctrls);
4300+
if (requestctrls[0] != NULL) {
4301+
ldap_control_free(requestctrls[0]);
43214302
}
43224303

43234304
if (rc != LDAP_SUCCESS ) {
43244305
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4325-
RETURN_FALSE;
4306+
RETVAL_FALSE;
4307+
goto cleanup;
43264308
}
43274309

43284310
rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
43294311
if ((rc < 0) || !ldap_res) {
43304312
rc = _get_lderrno(ld->link);
43314313
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4332-
RETURN_FALSE;
4314+
RETVAL_FALSE;
4315+
goto cleanup;
43334316
}
43344317

43354318
rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
43364319
if( rc != LDAP_SUCCESS ) {
43374320
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4338-
ldap_msgfree(ldap_res);
4339-
RETURN_FALSE;
4321+
RETVAL_FALSE;
4322+
goto cleanup;
43404323
}
43414324

4342-
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 1);
4325+
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
43434326
if( rc != LDAP_SUCCESS ) {
43444327
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4345-
RETURN_FALSE;
4328+
RETVAL_FALSE;
4329+
goto cleanup;
4330+
}
4331+
4332+
if (myargcount > 4) {
4333+
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
43464334
}
43474335

4336+
/* return */
43484337
if (lnewpw.bv_len == 0) {
43494338
if (lgenpasswd.bv_len == 0) {
43504339
RETVAL_EMPTY_STRING();
@@ -4358,11 +4347,16 @@ PHP_FUNCTION(ldap_exop_passwd)
43584347
RETVAL_FALSE;
43594348
}
43604349

4361-
if (myargcount > 4) {
4362-
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
4350+
cleanup:
4351+
if (lgenpasswd.bv_val != NULL) {
4352+
ldap_memfree(lgenpasswd.bv_val);
4353+
}
4354+
if (ldap_res != NULL) {
4355+
ldap_msgfree(ldap_res);
4356+
}
4357+
if (errmsg != NULL) {
4358+
ldap_memfree(errmsg);
43634359
}
4364-
4365-
ldap_memfree(lgenpasswd.bv_val);
43664360
}
43674361
/* }}} */
43684362
#endif

0 commit comments

Comments
 (0)