Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions Zend/tests/gh19844.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--TEST--
GH-19844: Bail from stream_close() in zend_shutdown_executor_values()
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip Aborts with STATUS_BAD_FUNCTION_TABLE on Windows');
?>
--FILE--
<?php

class Test {
public $context;
private static $nested = false;

function stream_open() {
return true;
}

function stream_read() {
return '.';
}
function stream_set_option() {}
function stream_stat() {}

function stream_eof() {
if (!Test::$nested) {
Test::$nested = true;
include 'Test://';
}
@trigger_error('Bail', E_USER_ERROR);
}

function stream_close() {
@trigger_error('Bail', E_USER_ERROR);
}
}

stream_wrapper_register('Test', Test::class);
include 'Test://';

?>
--EXPECTF--
Fatal error: Bail in %s on line %d

Fatal error: Bail in %s on line %d

Fatal error: Bail in %s on line %d
4 changes: 1 addition & 3 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,7 @@ void shutdown_destructors(void) /* {{{ */
ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
{
EG(flags) |= EG_FLAGS_IN_RESOURCE_SHUTDOWN;
zend_try {
zend_close_rsrc_list(&EG(regular_list));
} zend_end_try();
zend_close_rsrc_list(&EG(regular_list));

/* No PHP callback functions should be called after this point. */
EG(active) = 0;
Expand Down
24 changes: 17 additions & 7 deletions Zend/zend_list.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,15 +217,25 @@ void zend_close_rsrc_list(HashTable *ht)
/* Reload ht->arData on each iteration, as it may be reallocated. */
uint32_t i = ht->nNumUsed;

while (i-- > 0) {
zval *p = ZEND_HASH_ELEMENT(ht, i);
if (Z_TYPE_P(p) != IS_UNDEF) {
zend_resource *res = Z_PTR_P(p);
if (res->type >= 0) {
zend_resource_dtor(res);
retry:
zend_try {
while (i-- > 0) {
zval *p = ZEND_HASH_ELEMENT(ht, i);
if (Z_TYPE_P(p) != IS_UNDEF) {
zend_resource *res = Z_PTR_P(p);
if (res->type >= 0) {
zend_resource_dtor(res);
}
}
}
}
} zend_catch {
/* If we have bailed, we probably executed user code (e.g. user stream
* API). Keep closing resources so they don't leak. User handlers must be
* called now so they aren't called in zend_deactivate() on
* zend_destroy_rsrc_list(&EG(regular_list)). At that point, the executor
* has already shut down and the process would crash. */
goto retry;
} zend_end_try();
}


Expand Down
10 changes: 10 additions & 0 deletions ext/libxml/libxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#ifdef LIBXML_SCHEMAS_ENABLED
#include <libxml/relaxng.h>
#include <libxml/xmlschemas.h>
#include <libxml/xmlschemastypes.h>
#endif

#include "php_libxml.h"
Expand Down Expand Up @@ -928,7 +929,16 @@ PHP_LIBXML_API void php_libxml_initialize(void)
if (!php_libxml_initialized) {
/* we should be the only one's to ever init!! */
ZEND_IGNORE_LEAKS_BEGIN();

xmlInitParser();
#ifdef ZTS
# ifdef LIBXML_SCHEMAS_ENABLED
xmlSchemaInitTypes();
# endif
# ifdef LIBXML_RELAXNG_ENABLED
xmlRelaxNGInitTypes();
# endif
#endif
ZEND_IGNORE_LEAKS_END();

php_libxml_default_entity_loader = xmlGetExternalEntityLoader();
Expand Down
2 changes: 1 addition & 1 deletion ext/openssl/openssl_backend_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ STACK_OF(X509) *php_openssl_load_all_certs_from_file(
}

/* This loads from a file, a stack of x509/crl/pkey sets */
if (!(sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL))) {
if (!(sk = php_openssl_pem_read_bio_x509_info(in))) {
php_openssl_store_errors();
php_error_docref(NULL, E_WARNING, "Error reading the file, %s", cert_path);
sk_X509_free(stack);
Expand Down
5 changes: 5 additions & 0 deletions ext/openssl/openssl_backend_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,11 @@ X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in)
return PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
}

STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(BIO *in)
{
return PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
}

EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in)
{
return PEM_read_bio_PUBKEY(in, NULL, NULL, NULL);
Expand Down
5 changes: 5 additions & 0 deletions ext/openssl/openssl_backend_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,11 @@ X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in)
return xr;
}

STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(BIO *in)
{
return PEM_X509_INFO_read_bio_ex(in, NULL, NULL, NULL, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
}

EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in)
{
return PEM_read_bio_PUBKEY_ex(in, NULL, NULL, NULL, PHP_OPENSSL_LIBCTX, PHP_OPENSSL_PROPQ);
Expand Down
1 change: 1 addition & 0 deletions ext/openssl/php_openssl_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ zend_string *php_openssl_pkey_derive(EVP_PKEY *key, EVP_PKEY *peer_key, size_t r
X509 *php_openssl_pem_read_asn1_bio_x509(BIO *in);
X509 *php_openssl_pem_read_bio_x509(BIO *in);
X509_REQ *php_openssl_pem_read_bio_x509_req(BIO *in);
STACK_OF(X509_INFO) *php_openssl_pem_read_bio_x509_info(BIO *in);
EVP_PKEY *php_openssl_pem_read_bio_public_key(BIO *in);
EVP_PKEY *php_openssl_pem_read_bio_private_key(BIO *in, pem_password_cb *cb, void *u);
PKCS7 *php_openssl_pem_read_bio_pkcs7(BIO *in);
Expand Down
17 changes: 17 additions & 0 deletions ext/openssl/tests/gh19994.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--TEST--
GH-19994: openssl_get_cipher_methods inconsistent with fetched methods
--EXTENSIONS--
openssl
--FILE--
<?php

$ciphers = openssl_get_cipher_methods();

foreach ($ciphers as $cipher) {
if (openssl_cipher_iv_length($cipher) === false) {
var_dump($cipher);
}
}

?>
--EXPECT--
6 changes: 1 addition & 5 deletions ext/phar/phar.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,13 +595,9 @@ zend_result phar_metadata_tracker_unserialize_or_copy(phar_metadata_tracker *tra
const bool has_unserialize_options = unserialize_options != NULL && zend_hash_num_elements(unserialize_options) > 0;
/* It should be impossible to create a zval in a persistent phar/entry. */
ZEND_ASSERT(!persistent || Z_ISUNDEF(tracker->val));
ZEND_ASSERT(!EG(exception));

if (Z_ISUNDEF(tracker->val) || has_unserialize_options) {
if (EG(exception)) {
/* Because other parts of the phar code haven't been updated to check for exceptions after doing something that may throw,
* check for exceptions before potentially serializing/unserializing instead. */
return FAILURE;
}
/* Persistent phars should always be unserialized. */
const char *start;
/* Assert it should not be possible to create raw data in a persistent phar (i.e. from cache_list) */
Expand Down
51 changes: 14 additions & 37 deletions ext/phar/phar_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1711,7 +1711,7 @@ PHP_METHOD(Phar, buildFromDirectory)
{
char *error;
bool apply_reg = false;
zval arg, arg2, iter, iteriter, regexiter;
zval iter, iteriter, regexiter;
struct _phar_t pass;
zend_string *dir, *regex = NULL;

Expand All @@ -1727,34 +1727,16 @@ PHP_METHOD(Phar, buildFromDirectory)
RETURN_THROWS();
}

if (SUCCESS != object_init_ex(&iter, spl_ce_RecursiveDirectoryIterator)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
RETURN_THROWS();
}

ZVAL_STR(&arg, dir);
ZVAL_LONG(&arg2, SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);
zval args[2];
ZVAL_STR(&args[0], dir);
ZVAL_LONG(&args[1], SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS);

zend_call_known_instance_method_with_2_params(spl_ce_RecursiveDirectoryIterator->constructor,
Z_OBJ(iter), NULL, &arg, &arg2);

if (EG(exception)) {
zval_ptr_dtor(&iter);
if (SUCCESS != object_init_with_constructor(&iter, spl_ce_RecursiveDirectoryIterator, 2, args, NULL)) {
RETURN_THROWS();
}

if (SUCCESS != object_init_ex(&iteriter, spl_ce_RecursiveIteratorIterator)) {
if (SUCCESS != object_init_with_constructor(&iteriter, spl_ce_RecursiveIteratorIterator, 1, &iter, NULL)) {
zval_ptr_dtor(&iter);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate directory iterator for %s", phar_obj->archive->fname);
RETURN_THROWS();
}

zend_call_known_instance_method_with_1_params(spl_ce_RecursiveIteratorIterator->constructor,
Z_OBJ(iteriter), NULL, &iter);

if (EG(exception)) {
zval_ptr_dtor(&iter);
zval_ptr_dtor(&iteriter);
RETURN_THROWS();
}

Expand All @@ -1763,15 +1745,13 @@ PHP_METHOD(Phar, buildFromDirectory)
if (regex && ZSTR_LEN(regex) > 0) {
apply_reg = true;

if (SUCCESS != object_init_ex(&regexiter, spl_ce_RegexIterator)) {
ZVAL_COPY_VALUE(&args[0], &iteriter);
ZVAL_STR(&args[1], regex);

if (SUCCESS != object_init_with_constructor(&regexiter, spl_ce_RegexIterator, 2, args, NULL)) {
zval_ptr_dtor(&iteriter);
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate regex iterator for %s", phar_obj->archive->fname);
RETURN_THROWS();
}

ZVAL_STR(&arg2, regex);
zend_call_known_instance_method_with_2_params(spl_ce_RegexIterator->constructor,
Z_OBJ(regexiter), NULL, &iteriter, &arg2);
}

array_init(return_value);
Expand Down Expand Up @@ -2199,15 +2179,12 @@ static zend_object *phar_rename_archive(phar_archive_data **sphar, char *ext) /*
ce = phar_ce_archive;
}

if (SUCCESS != object_init_ex(&ret, ce)) {
zend_throw_exception_ex(spl_ce_BadMethodCallException, 0, "Unable to instantiate phar object when converting archive \"%s\"", phar->fname);
ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len);
zend_result result = object_init_with_constructor(&ret, ce, 1, &arg1, NULL);
zval_ptr_dtor_str(&arg1);
if (SUCCESS != result) {
return NULL;
}

ZVAL_STRINGL(&arg1, phar->fname, phar->fname_len);

zend_call_known_instance_method_with_1_params(ce->constructor, Z_OBJ(ret), NULL, &arg1);
zval_ptr_dtor(&arg1);
return Z_OBJ(ret);

err_reused_oldpath:
Expand Down