From 2335e9ed9ebdcd1939415e7236f5a1786ded7c9b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:58:06 +0100 Subject: [PATCH] Prevent unexpected array entry conversion when reading key When passing an array, the key entry can get converted to a string if it is an object, but this actually modifies the original array entry. The test originally outputted: ``` array(2) { [0]=> string(...) => ... [1]=> string(0) "" } ``` This is unexpected. Use zval_try_get_string() to prevent this behaviour. --- ext/openssl/openssl.c | 18 ++++++++----- ..._pkey_export_to_file_object_to_string.phpt | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4b4a8d7f35667..8ea6315fa5c9e 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -3571,19 +3571,21 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) { TMP_CLEAN; } - if (!try_convert_to_string(val)) { + zend_string *val_str = zval_try_get_string(val); + if (!val_str) { TMP_CLEAN; } - if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) { - if (!php_openssl_check_path_str(Z_STR_P(val), file_path, arg_num)) { + if (ZSTR_LEN(val_str) > 7 && memcmp(ZSTR_VAL(val_str), "file://", sizeof("file://") - 1) == 0) { + if (!php_openssl_check_path_str(val_str, file_path, arg_num)) { + zend_string_release_ex(val_str, false); TMP_CLEAN; } is_file = true; } /* it's an X509 file/cert of some kind, and we need to extract the data from that */ if (public_key) { - cert = php_openssl_x509_from_str(Z_STR_P(val), arg_num, false, NULL); + cert = php_openssl_x509_from_str(val_str, arg_num, false, NULL); if (cert) { free_cert = 1; @@ -3593,10 +3595,11 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (is_file) { in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); } else { - in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val)); + in = BIO_new_mem_buf(ZSTR_VAL(val_str), (int)ZSTR_LEN(val_str)); } if (in == NULL) { php_openssl_store_errors(); + zend_string_release_ex(val_str, false); TMP_CLEAN; } key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL); @@ -3609,10 +3612,11 @@ static EVP_PKEY *php_openssl_pkey_from_zval( if (is_file) { in = BIO_new_file(file_path, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY)); } else { - in = BIO_new_mem_buf(Z_STRVAL_P(val), (int)Z_STRLEN_P(val)); + in = BIO_new_mem_buf(ZSTR_VAL(val_str), (int)ZSTR_LEN(val_str)); } if (in == NULL) { + zend_string_release_ex(val_str, false); TMP_CLEAN; } if (passphrase == NULL) { @@ -3625,6 +3629,8 @@ static EVP_PKEY *php_openssl_pkey_from_zval( } BIO_free(in); } + + zend_string_release_ex(val_str, false); } if (key == NULL) { diff --git a/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt b/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt new file mode 100644 index 0000000000000..0e504bfa4ac63 --- /dev/null +++ b/ext/openssl/tests/openssl_pkey_export_to_file_object_to_string.phpt @@ -0,0 +1,27 @@ +--TEST-- +openssl_pkey_export_to_file object to string conversion +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + object(Test)#1 (0) { + } + [1]=> + string(0) "" +}