Commit ea67883a1ff for php.net
commit ea67883a1ff3528d233491e844549a04da975622
Author: Gina Peter Banyard <girgias@php.net>
Date: Mon Apr 27 15:05:32 2026 +0100
ext/phar: refactor phar_create_signature() to return a zend_string* (#21843)
Instead of using out parameters.
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 2ab799ab8c8..a81a62a188f 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -2995,17 +2995,12 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen
switch(phar->sig_flags) {
default: {
- char *digest = NULL;
- size_t digest_len;
-
char *signature_error = NULL;
- if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, &signature_error)) {
+ zend_string *signature = phar_create_signature(phar, newfile, &signature_error);
+ if (!signature) {
spprintf(error, 0, "phar error: unable to write signature: %s", signature_error);
efree(signature_error);
- if (digest) {
- efree(digest);
- }
if (must_close_old_file) {
php_stream_close(oldfile);
}
@@ -3013,14 +3008,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen
return EOF;
}
- php_stream_write(newfile, digest, digest_len);
- efree(digest);
+ php_stream_write(newfile, ZSTR_VAL(signature), ZSTR_LEN(signature));
if (phar->sig_flags == PHAR_SIG_OPENSSL ||
phar->sig_flags == PHAR_SIG_OPENSSL_SHA256 ||
phar->sig_flags == PHAR_SIG_OPENSSL_SHA512) {
- phar_set_32(sig_buf, digest_len);
+ phar_set_32(sig_buf, ZSTR_LEN(signature));
php_stream_write(newfile, sig_buf, 4);
}
+ zend_string_release_ex(signature, false);
break;
}
}
diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h
index 36fa2b54350..df4e58c7adb 100644
--- a/ext/phar/phar_internal.h
+++ b/ext/phar/phar_internal.h
@@ -413,7 +413,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *ali
zend_result phar_free_alias(const phar_archive_data *phar);
zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error);
zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error);
-ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error);
+ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error);
/* utility functions */
zend_string *phar_create_default_stub(const zend_string *php_index_str, const zend_string *web_index_str, char **error);
diff --git a/ext/phar/tar.c b/ext/phar/tar.c
index a7c02e35273..761246000dd 100644
--- a/ext/phar/tar.c
+++ b/ext/phar/tar.c
@@ -968,9 +968,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze
phar_entry_info entry = {0};
php_stream *oldfile, *newfile;
bool must_close_old_file = false;
- size_t signature_length;
struct _phar_pass_tar_info pass;
- char *buf, *signature, sigbuf[8];
+ char *buf, sigbuf[8];
entry.flags = PHAR_ENT_PERM_DEF_FILE;
entry.timestamp = time(NULL);
@@ -1168,7 +1167,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze
/* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */
if (!phar->is_data || phar->sig_flags) {
char *signature_error = NULL;
- if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) {
+ zend_string *signature = phar_create_signature(phar, newfile, &signature_error);
+ if (!signature) {
spprintf(error, 0, "phar error: unable to write signature to tar-based phar: %s", signature_error);
efree(signature_error);
@@ -1184,7 +1184,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze
if (entry.fp == NULL) {
*error = estrdup("phar error: unable to create temporary file");
- efree(signature);
+ zend_string_release_ex(signature, false);
if (must_close_old_file) {
php_stream_close(oldfile);
}
@@ -1203,10 +1203,10 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze
# define PHAR_SET_32(destination, source) memcpy(destination, &source, 4)
#endif
PHAR_SET_32(sigbuf, phar->sig_flags);
- PHAR_SET_32(sigbuf + 4, signature_length);
+ PHAR_SET_32(sigbuf + 4, ZSTR_LEN(signature));
- if (8 != php_stream_write(entry.fp, sigbuf, 8) || signature_length != php_stream_write(entry.fp, signature, signature_length)) {
- efree(signature);
+ if (8 != php_stream_write(entry.fp, sigbuf, 8) || ZSTR_LEN(signature) != php_stream_write(entry.fp, ZSTR_VAL(signature), ZSTR_LEN(signature))) {
+ zend_string_release_ex(signature, false);
spprintf(error, 0, "phar error: unable to write signature to tar-based phar %s", ZSTR_VAL(phar->fname));
if (must_close_old_file) {
@@ -1218,11 +1218,11 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze
ALLOCA_FLAG(use_heap);
ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap);
- efree(signature);
- entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8;
+ entry.uncompressed_filesize = entry.compressed_filesize = ZSTR_LEN(signature) + 8;
/* throw out return value and write the signature */
phar_tar_writeheaders_int(&entry, &pass);
ZSTR_ALLOCA_FREE(entry.filename, use_heap);
+ zend_string_release_ex(signature, false);
if (*error) {
if (must_close_old_file) {
diff --git a/ext/phar/util.c b/ext/phar/util.c
index 491a07c4dd2..ad7cdd6c9ae 100644
--- a/ext/phar/util.c
+++ b/ext/phar/util.c
@@ -1783,8 +1783,9 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s
}
/* }}} */
-ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */
+ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error) /* {{{ */
{
+ zend_string *signature = NULL;
unsigned char buf[1024];
size_t sig_len;
@@ -1807,8 +1808,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
}
PHP_SHA512Final(digest, &context);
- *signature = estrndup((char *) digest, 64);
- *signature_length = 64;
+ signature = zend_string_init((const char*)digest, 64, false);
break;
}
default:
@@ -1825,8 +1825,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
}
PHP_SHA256Final(digest, &context);
- *signature = estrndup((char *) digest, 32);
- *signature_length = 32;
+ signature = zend_string_init((const char*)digest, 32, false);
break;
}
case PHAR_SIG_OPENSSL_SHA512:
@@ -1852,7 +1851,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
if (in == NULL) {
spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
@@ -1860,14 +1859,14 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
if (!key) {
*error = estrdup("unable to process private key");
- return FAILURE;
+ return NULL;
}
md_ctx = EVP_MD_CTX_create();
if (md_ctx == NULL) {
EVP_PKEY_free(key);
spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
siglen = EVP_PKEY_size(key);
@@ -1878,7 +1877,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
EVP_MD_CTX_destroy(md_ctx);
efree(sigbuf);
spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
@@ -1887,7 +1886,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
EVP_MD_CTX_destroy(md_ctx);
efree(sigbuf);
spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
}
@@ -1896,12 +1895,14 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
EVP_MD_CTX_destroy(md_ctx);
efree(sigbuf);
spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
sigbuf[siglen] = '\0';
EVP_PKEY_free(key);
EVP_MD_CTX_destroy(md_ctx);
+ signature = zend_string_init((const char*)sigbuf, siglen, false);
+ efree(sigbuf);
#else
size_t siglen;
sigbuf = NULL;
@@ -1910,11 +1911,11 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
if (FAILURE == phar_call_openssl_signverify(true, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) {
spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname));
- return FAILURE;
+ return NULL;
}
+ signature = zend_string_init((const char*)sigbuf, siglen, false);
+ efree(sigbuf);
#endif
- *signature = (char *) sigbuf;
- *signature_length = siglen;
}
break;
case PHAR_SIG_SHA1: {
@@ -1928,8 +1929,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
}
PHP_SHA1Final(digest, &context);
- *signature = estrndup((char *) digest, 20);
- *signature_length = 20;
+ signature = zend_string_init((const char*)digest, 20, false);
break;
}
case PHAR_SIG_MD5: {
@@ -1943,14 +1943,13 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar
}
PHP_MD5Final(digest, &context);
- *signature = estrndup((char *) digest, 16);
- *signature_length = 16;
+ signature = zend_string_init((const char*)digest, 16, false);
break;
}
}
- phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature);
- return SUCCESS;
+ phar->sig_len = phar_hex_str(ZSTR_VAL(signature), ZSTR_LEN(signature), &phar->signature);
+ return signature;
}
/* }}} */
diff --git a/ext/phar/zip.c b/ext/phar/zip.c
index 28e1a3d5641..da934a4c004 100644
--- a/ext/phar/zip.c
+++ b/ext/phar/zip.c
@@ -1148,8 +1148,7 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar
{
/* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */
if (!phar->is_data || phar->sig_flags) {
- size_t signature_length;
- char *signature, sigbuf[8];
+ char sigbuf[8];
phar_entry_info entry = {0};
php_stream *newfile;
zend_off_t tell;
@@ -1171,11 +1170,10 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar
}
char *signature_error = NULL;
- if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) {
- if (signature_error) {
- spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", signature_error);
- efree(signature_error);
- }
+ zend_string *signature = phar_create_signature(phar, newfile, &signature_error);
+ if (!signature) {
+ spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", signature_error);
+ efree(signature_error);
php_stream_close(newfile);
return FAILURE;
@@ -1185,17 +1183,17 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar
entry.fp_type = PHAR_MOD;
entry.is_modified = 1;
if (entry.fp == NULL) {
- efree(signature);
+ zend_string_release_ex(signature, false);
spprintf(pass->error, 0, "phar error: unable to create temporary file for signature");
php_stream_close(newfile);
return FAILURE;
}
PHAR_SET_32(sigbuf, phar->sig_flags);
- PHAR_SET_32(sigbuf + 4, signature_length);
+ PHAR_SET_32(sigbuf + 4, ZSTR_LEN(signature));
- if (Z_UL(8) != php_stream_write(entry.fp, sigbuf, 8) || signature_length != php_stream_write(entry.fp, signature, signature_length)) {
- efree(signature);
+ if (Z_UL(8) != php_stream_write(entry.fp, sigbuf, 8) || ZSTR_LEN(signature) != php_stream_write(entry.fp, ZSTR_VAL(signature), ZSTR_LEN(signature))) {
+ zend_string_release_ex(signature, false);
if (pass->error) {
spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar %s", ZSTR_VAL(phar->fname));
}
@@ -1206,13 +1204,13 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar
ALLOCA_FLAG(use_heap);
ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap);
- efree(signature);
- entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8;
+ entry.uncompressed_filesize = entry.compressed_filesize = ZSTR_LEN(signature) + 8;
entry.phar = phar;
/* throw out return value and write the signature */
phar_zip_changed_apply_int(&entry, (void *)pass);
ZSTR_ALLOCA_FREE(entry.filename, use_heap);
php_stream_close(newfile);
+ zend_string_release_ex(signature, false);
if (pass->error && *(pass->error)) {
/* error is set by writeheaders */