diff --git a/.github/actions/macos-update-clang/action.yml b/.github/actions/macos-update-clang/action.yml new file mode 100644 index 000000000000..bceb431aed5a --- /dev/null +++ b/.github/actions/macos-update-clang/action.yml @@ -0,0 +1,17 @@ +name: Update clang +runs: + using: composite + steps: + - shell: bash + run: | + softwareupdate -l + label=$((softwareupdate -l 2>/dev/null | grep 'Label:' | grep -o 'Command Line Tools for Xcode.*' | head -1) || echo '') + if [ -n "$label" ]; then + softwareupdate -i "$label" + xcode_path=$(ls -1 '/Applications' | grep 'Xcode_.*\.app' | head -1) + sudo xcode-select -s "/Applications/$xcode_path" + else + echo "Not found." + fi + which clang + clang -v diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 68a3a5c737d2..48628896f498 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -363,6 +363,8 @@ jobs: uses: actions/checkout@v5 with: ref: ${{ inputs.branch }} + - name: Update clang + uses: ./.github/actions/macos-update-clang - name: brew uses: ./.github/actions/brew - name: ./configure diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 41a9d51e9936..414969378dc7 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -239,6 +239,8 @@ jobs: steps: - name: git checkout uses: actions/checkout@v5 + - name: Update clang + uses: ./.github/actions/macos-update-clang - name: brew uses: ./.github/actions/brew - name: ccache diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index e9acd1899066..9e566a4ed1dc 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -425,7 +425,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, const HashTable *control_ht) { zval* val; - zend_string *control_oid; + zend_string *control_oid, *control_oid_tmp; char** ldap_attrs = NULL; LDAPSortKey** sort_keys = NULL; zend_string *tmpstring = NULL, **tmpstrings1 = NULL, **tmpstrings2 = NULL; @@ -436,8 +436,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT return -1; } - control_oid = zval_get_string(val); - if (EG(exception)) { + control_oid = zval_try_get_tmp_string(val, &control_oid_tmp); + if (!control_oid) { return -1; } @@ -453,8 +453,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT if ((val = zend_hash_find(control_ht, ZSTR_KNOWN(ZEND_STR_VALUE))) != NULL) { if (Z_TYPE_P(val) != IS_ARRAY) { - tmpstring = zval_get_string(val); - if (EG(exception)) { + tmpstring = zval_try_get_string(val); + if (!tmpstring) { rc = -1; goto failure; } @@ -468,8 +468,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT pagesize = zval_get_long(tmp); } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + tmpstring = zval_try_get_string(tmp); + if (!tmpstring) { rc = -1; goto failure; } @@ -488,8 +488,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT rc = -1; zend_value_error("%s(): Control must have a \"filter\" key", get_active_function_name()); } else { - zend_string* assert = zval_get_string(tmp); - if (EG(exception)) { + zend_string* assert = zval_try_get_string(tmp); + if (!assert) { rc = -1; goto failure; } @@ -516,8 +516,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT rc = -1; php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); } else { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + tmpstring = zval_try_get_string(tmp); + if (!tmpstring) { rc = -1; goto failure; } @@ -555,8 +555,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT goto failure; } - tmpstrings1[num_tmpstrings1] = zval_get_string(attr); - if (EG(exception)) { + tmpstrings1[num_tmpstrings1] = zval_try_get_string(attr); + if (!tmpstrings1[num_tmpstrings1]) { rc = -1; goto failure; } @@ -603,8 +603,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT goto failure; } sort_keys[i] = emalloc(sizeof(LDAPSortKey)); - tmpstrings1[num_tmpstrings1] = zval_get_string(tmp); - if (EG(exception)) { + tmpstrings1[num_tmpstrings1] = zval_try_get_string(tmp); + if (!tmpstrings1[num_tmpstrings1]) { rc = -1; goto failure; } @@ -612,8 +612,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT ++num_tmpstrings1; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) { - tmpstrings2[num_tmpstrings2] = zval_get_string(tmp); - if (EG(exception)) { + tmpstrings2[num_tmpstrings2] = zval_try_get_string(tmp); + if (!tmpstrings2[num_tmpstrings2]) { rc = -1; goto failure; } @@ -659,8 +659,8 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT } if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + tmpstring = zval_try_get_string(tmp); + if (!tmpstring) { rc = -1; goto failure; } @@ -684,14 +684,15 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT goto failure; } + zend_string *context_str = NULL; if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) { - tmpstring = zval_get_string(tmp); - if (EG(exception)) { + context_str = zval_try_get_string(tmp); + if (!context_str) { rc = -1; goto failure; } - context.bv_val = ZSTR_VAL(tmpstring); - context.bv_len = ZSTR_LEN(tmpstring); + context.bv_val = ZSTR_VAL(context_str); + context.bv_len = ZSTR_LEN(context_str); vlvInfo.ldvlv_context = &context; } else { vlvInfo.ldvlv_context = NULL; @@ -703,6 +704,9 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc); } + if (context_str) { + zend_string_release_ex(context_str, false); + } } else { zend_type_error("%s(): Control OID %s cannot be of type array", get_active_function_name(), ZSTR_VAL(control_oid)); rc = -1; @@ -714,7 +718,7 @@ static int php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, const HashT } failure: - zend_string_release(control_oid); + zend_tmp_string_release(control_oid_tmp); if (tmpstring != NULL) { zend_string_release(tmpstring); } @@ -2791,8 +2795,8 @@ PHP_FUNCTION(ldap_modify_batch) zend_ulong value_index = 0; zval *modification_value_zv = NULL; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(modification_values), modification_value_zv) { - zend_string *modval = zval_get_string(modification_value_zv); - if (EG(exception)) { + zend_string *modval = zval_try_get_string(modification_value_zv); + if (!modval) { RETVAL_FALSE; ldap_mods[modification_index]->mod_bvalues[value_index] = NULL; num_mods = modification_index + 1; diff --git a/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt new file mode 100644 index 000000000000..5829ad24faf5 --- /dev/null +++ b/ext/ldap/tests/ldap_set_option_leak_attrvalue_context.phpt @@ -0,0 +1,34 @@ +--TEST-- +ldap_set_option() - Leaks attrvalue and context +--EXTENSIONS-- +ldap +--FILE-- + "2.16.840.1.113730.3.4.9", "value" => ["attrvalue" => $attrvalue, "context" => $context, "before" => 0, "after" => 0]], +]; + +ldap_set_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls); +ldap_get_option($link, LDAP_OPT_CLIENT_CONTROLS, $controls_out); + +var_dump($controls_out); +?> +--EXPECTF-- +array(1) { + ["2.16.840.1.113730.3.4.9"]=> + array(3) { + ["oid"]=> + string(23) "2.16.840.1.113730.3.4.9" + ["iscritical"]=> + bool(false) + ["value"]=> + string(28) "0%0%0 attrvaluecontext" + } +}