Skip to content

Commit 08dcb8e

Browse files
author
Côme Chilliet
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Updated NEWS fix memory leaks in ext/ldap/ldap.c fix memory leaks in ext/ldap/ldap.c
2 parents 2dbb4ec + 1ba8835 commit 08dcb8e

File tree

2 files changed

+98
-102
lines changed

2 files changed

+98
-102
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ PHP NEWS
1111
- JIT:
1212
. Fixed bug #79864 (JIT segfault in Symfony OptionsResolver). (Dmitry)
1313

14+
- LDAP:
15+
. Fixed memory leaks. (ptomulik)
16+
1417
- OCI8:
1518
. Modernized oci_register_taf_callback() callable argument parsing
1619
implementation. (girgias)

ext/ldap/ldap.c

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

170170
if (ctrl->ldctl_value.bv_len) {
171+
/* ldap_parse_pageresponse_control() allocates lcookie.bv_val */
171172
rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie);
172173
} else {
173174
/* ldap_parse_pageresponse_control will crash if value is empty */
174175
rc = -1;
175176
}
177+
176178
if ( rc == LDAP_SUCCESS ) {
177179
array_init(&value);
178180
add_assoc_long(&value, "size", lestimated);
@@ -181,6 +183,10 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
181183
} else {
182184
add_assoc_null(array, "value");
183185
}
186+
187+
if (lcookie.bv_val) {
188+
ldap_memfree(lcookie.bv_val);
189+
}
184190
} else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) {
185191
BerElement *ber;
186192
struct berval bv;
@@ -299,27 +305,23 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
299305
control_iscritical = 0;
300306
}
301307

302-
struct berval *control_value = NULL;
308+
BerElement *ber = NULL;
309+
struct berval control_value = { 0L, NULL };
310+
int control_value_alloc = 0;
303311

304312
if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) {
305313
if (Z_TYPE_P(val) != IS_ARRAY) {
306-
control_value = ber_memalloc(sizeof * control_value);
307-
if (control_value == NULL) {
314+
tmpstring = zval_get_string(val);
315+
if (EG(exception)) {
308316
rc = -1;
309-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
310-
} else {
311-
tmpstring = zval_get_string(val);
312-
if (EG(exception)) {
313-
rc = -1;
314-
goto failure;
315-
}
316-
control_value->bv_val = ZSTR_VAL(tmpstring);
317-
control_value->bv_len = ZSTR_LEN(tmpstring);
317+
goto failure;
318318
}
319+
control_value.bv_val = ZSTR_VAL(tmpstring);
320+
control_value.bv_len = ZSTR_LEN(tmpstring);
319321
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_PAGEDRESULTS) == 0) {
320322
zval* tmp;
321323
int pagesize = 1;
322-
struct berval cookie = { 0, NULL };
324+
struct berval cookie = { 0L, NULL };
323325
if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) {
324326
pagesize = zval_get_long(tmp);
325327
}
@@ -332,15 +334,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
332334
cookie.bv_val = ZSTR_VAL(tmpstring);
333335
cookie.bv_len = ZSTR_LEN(tmpstring);
334336
}
335-
control_value = ber_memalloc(sizeof * control_value);
336-
if (control_value == NULL) {
337-
rc = -1;
338-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
339-
} else {
340-
rc = ldap_create_page_control_value(ld, pagesize, &cookie, control_value);
341-
if (rc != LDAP_SUCCESS) {
342-
php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
343-
}
337+
/* ldap_create_page_control_value() allocates memory for control_value.bv_val */
338+
control_value_alloc = 1;
339+
rc = ldap_create_page_control_value(ld, pagesize, &cookie, &control_value);
340+
if (rc != LDAP_SUCCESS) {
341+
php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc);
344342
}
345343
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_ASSERT) == 0) {
346344
zval* tmp;
@@ -354,19 +352,15 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
354352
rc = -1;
355353
goto failure;
356354
}
357-
control_value = ber_memalloc(sizeof * control_value);
358-
if (control_value == NULL) {
359-
rc = -1;
360-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
361-
} else {
362-
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
363-
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
364-
int success = LDAP_SUCCESS;
365-
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
366-
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), control_value);
367-
if (rc != LDAP_SUCCESS) {
368-
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
369-
}
355+
/* ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves
356+
See http://www.openldap.org/its/index.cgi/Incoming?id=8674 */
357+
int success = LDAP_SUCCESS;
358+
ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success);
359+
/* ldap_create_assertion_control_value() allocates memory for control_value.bv_val */
360+
control_value_alloc = 1;
361+
rc = ldap_create_assertion_control_value(ld, ZSTR_VAL(assert), &control_value);
362+
if (rc != LDAP_SUCCESS) {
363+
php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc);
370364
}
371365
zend_string_release(assert);
372366
}
@@ -376,9 +370,8 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
376370
rc = -1;
377371
php_error_docref(NULL, E_WARNING, "Filter missing from control value array");
378372
} else {
379-
BerElement *vrber = ber_alloc_t(LBER_USE_DER);
380-
control_value = ber_memalloc(sizeof * control_value);
381-
if ((control_value == NULL) || (vrber == NULL)) {
373+
ber = ber_alloc_t(LBER_USE_DER);
374+
if (ber == NULL) {
382375
rc = -1;
383376
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
384377
} else {
@@ -387,14 +380,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
387380
rc = -1;
388381
goto failure;
389382
}
390-
if (ldap_put_vrFilter(vrber, ZSTR_VAL(tmpstring)) == -1) {
391-
ber_free(vrber, 1);
383+
if (ldap_put_vrFilter(ber, ZSTR_VAL(tmpstring)) == -1) {
392384
rc = -1;
393385
php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", ZSTR_VAL(tmpstring));
394-
} else {
395-
if (ber_flatten2(vrber, control_value, 0) == -1) {
396-
rc = -1;
397-
}
386+
} else if (ber_flatten2(ber, &control_value, control_value_alloc) == -1) {
387+
rc = -1;
398388
}
399389
}
400390
}
@@ -404,10 +394,9 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
404394
rc = -1;
405395
php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array");
406396
} else {
407-
BerElement *ber = ber_alloc_t(LBER_USE_DER);
397+
ber = ber_alloc_t(LBER_USE_DER);
408398

409-
control_value = ber_memalloc(sizeof * control_value);
410-
if ((control_value == NULL) || (ber == NULL)) {
399+
if (ber == NULL) {
411400
rc = -1;
412401
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
413402
} else {
@@ -443,7 +432,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
443432
php_error_docref(NULL, E_WARNING, "Failed to encode attribute list");
444433
} else {
445434
int err;
446-
err = ber_flatten2(ber, control_value, 0);
435+
err = ber_flatten2(ber, &control_value, control_value_alloc);
447436
if (err < 0) {
448437
rc = -1;
449438
php_error_docref(NULL, E_WARNING, "Failed to encode control value (%d)", err);
@@ -502,15 +491,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
502491
}
503492
}
504493
sort_keys[num_keys] = NULL;
505-
control_value = ber_memalloc(sizeof * control_value);
506-
if (control_value == NULL) {
507-
rc = -1;
508-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
509-
} else {
510-
rc = ldap_create_sort_control_value(ld, sort_keys, control_value);
511-
if (rc != LDAP_SUCCESS) {
512-
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
513-
}
494+
/* ldap_create_sort_control_value() allocates memory for control_value.bv_val */
495+
control_value_alloc = 1;
496+
rc = ldap_create_sort_control_value(ld, sort_keys, &control_value);
497+
if (rc != LDAP_SUCCESS) {
498+
php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc);
514499
}
515500
} else if (strcmp(ZSTR_VAL(control_oid), LDAP_CONTROL_VLVREQUEST) == 0) {
516501
zval* tmp;
@@ -572,15 +557,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
572557
vlvInfo.ldvlv_context = NULL;
573558
}
574559

575-
control_value = ber_memalloc(sizeof * control_value);
576-
if (control_value == NULL) {
577-
rc = -1;
578-
php_error_docref(NULL, E_WARNING, "Failed to allocate control value");
579-
} else {
580-
rc = ldap_create_vlv_control_value(ld, &vlvInfo, control_value);
581-
if (rc != LDAP_SUCCESS) {
582-
php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
583-
}
560+
/* ldap_create_vlv_control_value() allocates memory for control_value.bv_val */
561+
control_value_alloc = 1;
562+
rc = ldap_create_vlv_control_value(ld, &vlvInfo, &control_value);
563+
if (rc != LDAP_SUCCESS) {
564+
php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc);
584565
}
585566
} else {
586567
php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", ZSTR_VAL(control_oid));
@@ -589,7 +570,7 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
589570
}
590571

591572
if (rc == LDAP_SUCCESS) {
592-
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, control_value, 1, ctrl);
573+
rc = ldap_control_create(ZSTR_VAL(control_oid), control_iscritical, &control_value, 1, ctrl);
593574
}
594575

595576
failure:
@@ -611,9 +592,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
611592
}
612593
efree(tmpstrings2);
613594
}
614-
if (control_value != NULL) {
615-
ber_memfree(control_value);
616-
control_value = NULL;
595+
if (control_value.bv_val != NULL && control_value_alloc != 0) {
596+
ber_memfree(control_value.bv_val);
597+
}
598+
if (ber != NULL) {
599+
ber_free(ber, 1);
617600
}
618601
if (ldap_attrs != NULL) {
619602
efree(ldap_attrs);
@@ -1445,7 +1428,7 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
14451428
zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
14461429
char **ldap_attrs = NULL;
14471430
ldap_linkdata *ld = NULL;
1448-
LDAPMessage *ldap_res;
1431+
LDAPMessage *ldap_res = NULL;
14491432
LDAPControl **lserverctrls = NULL;
14501433
int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
14511434
int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
@@ -1645,6 +1628,11 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
16451628
&& errno != LDAP_REFERRAL
16461629
#endif
16471630
) {
1631+
/* ldap_res should be freed regardless of return value of ldap_search_ext_s()
1632+
* see: https://linux.die.net/man/3/ldap_search_ext_s */
1633+
if (ldap_res != NULL) {
1634+
ldap_msgfree(ldap_res);
1635+
}
16481636
php_error_docref(NULL, E_WARNING, "Search: %s", ldap_err2string(errno));
16491637
ret = 0;
16501638
} else {
@@ -3902,7 +3890,7 @@ PHP_FUNCTION(ldap_control_paged_result)
39023890
zval *link;
39033891
char *cookie = NULL;
39043892
size_t cookie_len = 0;
3905-
struct berval lcookie = { 0, NULL };
3893+
struct berval lcookie = { 0L, NULL };
39063894
ldap_linkdata *ld;
39073895
LDAP *ldap;
39083896
BerElement *ber = NULL;
@@ -4190,17 +4178,15 @@ PHP_FUNCTION(ldap_exop)
41904178
PHP_FUNCTION(ldap_exop_passwd)
41914179
{
41924180
zval *link, *serverctrls;
4193-
struct berval luser, loldpw, lnewpw, lgenpasswd;
4194-
LDAPControl **lserverctrls = NULL, **requestctrls = NULL;
4195-
LDAPControl *ctrl, **ctrlp;
4196-
LDAPMessage* ldap_res;
4181+
struct berval luser = { 0L, NULL };
4182+
struct berval loldpw = { 0L, NULL };
4183+
struct berval lnewpw = { 0L, NULL };
4184+
struct berval lgenpasswd = { 0L, NULL };
4185+
LDAPControl *ctrl, **lserverctrls = NULL, *requestctrls[2] = { NULL, NULL };
4186+
LDAPMessage* ldap_res = NULL;
41974187
ldap_linkdata *ld;
41984188
int rc, myargcount = ZEND_NUM_ARGS(), msgid, err;
4199-
char* errmsg;
4200-
4201-
luser.bv_len = 0;
4202-
loldpw.bv_len = 0;
4203-
lnewpw.bv_len = 0;
4189+
char* errmsg = NULL;
42044190

42054191
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) {
42064192
RETURN_THROWS();
@@ -4212,16 +4198,10 @@ PHP_FUNCTION(ldap_exop_passwd)
42124198

42134199
switch (myargcount) {
42144200
case 5:
4215-
requestctrls = safe_emalloc(2, sizeof(*requestctrls), 0);
4216-
*requestctrls = NULL;
4217-
ctrlp = requestctrls;
4218-
4201+
/* ldap_create_passwordpolicy_control() allocates ctrl */
42194202
if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) {
4220-
*ctrlp = ctrl;
4221-
++ctrlp;
4203+
requestctrls[0] = ctrl;
42224204
}
4223-
4224-
*ctrlp = NULL;
42254205
}
42264206

42274207
/* asynchronous call to get result and controls */
@@ -4231,35 +4211,43 @@ PHP_FUNCTION(ldap_exop_passwd)
42314211
requestctrls,
42324212
NULL, &msgid);
42334213

4234-
if (requestctrls != NULL) {
4235-
efree(requestctrls);
4214+
if (requestctrls[0] != NULL) {
4215+
ldap_control_free(requestctrls[0]);
42364216
}
42374217

42384218
if (rc != LDAP_SUCCESS ) {
42394219
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4240-
RETURN_FALSE;
4220+
RETVAL_FALSE;
4221+
goto cleanup;
42414222
}
42424223

42434224
rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
42444225
if ((rc < 0) || !ldap_res) {
42454226
rc = _get_lderrno(ld->link);
42464227
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4247-
RETURN_FALSE;
4228+
RETVAL_FALSE;
4229+
goto cleanup;
42484230
}
42494231

42504232
rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd);
42514233
if( rc != LDAP_SUCCESS ) {
42524234
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4253-
ldap_msgfree(ldap_res);
4254-
RETURN_FALSE;
4235+
RETVAL_FALSE;
4236+
goto cleanup;
42554237
}
42564238

4257-
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 1);
4239+
rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 0);
42584240
if( rc != LDAP_SUCCESS ) {
42594241
php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
4260-
RETURN_FALSE;
4242+
RETVAL_FALSE;
4243+
goto cleanup;
4244+
}
4245+
4246+
if (myargcount > 4) {
4247+
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
42614248
}
42624249

4250+
/* return */
42634251
if (lnewpw.bv_len == 0) {
42644252
if (lgenpasswd.bv_len == 0) {
42654253
RETVAL_EMPTY_STRING();
@@ -4273,11 +4261,16 @@ PHP_FUNCTION(ldap_exop_passwd)
42734261
RETVAL_FALSE;
42744262
}
42754263

4276-
if (myargcount > 4) {
4277-
_php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0);
4264+
cleanup:
4265+
if (lgenpasswd.bv_val != NULL) {
4266+
ldap_memfree(lgenpasswd.bv_val);
4267+
}
4268+
if (ldap_res != NULL) {
4269+
ldap_msgfree(ldap_res);
4270+
}
4271+
if (errmsg != NULL) {
4272+
ldap_memfree(errmsg);
42784273
}
4279-
4280-
ldap_memfree(lgenpasswd.bv_val);
42814274
}
42824275
/* }}} */
42834276
#endif

0 commit comments

Comments
 (0)