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
6 changes: 5 additions & 1 deletion UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ PHP 8.6 UPGRADE NOTES

- Zip:
. Added ZipArchive::openString() method.
. Added ZipArchive::closeString() method.

========================================
7. New Classes and Interfaces
Expand Down Expand Up @@ -447,7 +448,10 @@ PHP 8.6 UPGRADE NOTES
. Improved performance of str_split().

- URI:
. Reduced allocations when reading RFC3986 IPv6/IPFuture hosts and paths.
. Reduced allocations when reading IPv6/IPFuture hosts and paths with
Uri\Rfc3986\Uri.
. Improved performance and memory consumption when using normalizing
(non-raw) getters on already-normalized URIs with Uri\Rfc3986\Uri.

- Zip:
. Avoid string copies in ZipArchive::addFromString().
30 changes: 30 additions & 0 deletions Zend/tests/display_error_function_args.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--TEST--
Displaying function arguments in errors
--INI--
error_include_args=On
--FILE--
<?php

// A function that sets its own parameters in docref call, to compare
unlink('/');

// Something with sensitive parameters that exists in a minimal build,
// and also doesn't set anything in the docref call. cost is set to 4
// to keep the test fast
$flags = ["salt" => "123456789012345678901" . chr(0), "cost" => 4];
password_hash("test", PASSWORD_BCRYPT, $flags);

ini_set("error_include_args", "Off");

unlink('/');
password_hash("test", PASSWORD_BCRYPT, $flags);

?>
--EXPECTF--
Warning: unlink('/'): %s in %s on line %d

Warning: password_hash(Object(SensitiveParameterValue), '2y', Array): The "salt" option has been ignored, since providing a custom salt is no longer supported in %s on line %d

Warning: unlink(/): %s in %s on line %d

Warning: password_hash(): The "salt" option has been ignored, since providing a custom salt is no longer supported in %s on line %d
87 changes: 60 additions & 27 deletions Zend/zend_exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ ZEND_METHOD(ErrorException, getSeverity)
} \
} while (0)

static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
static void build_trace_args(zval *arg, smart_str *str) /* {{{ */
{
/* the trivial way would be to do
* convert_to_string(arg);
Expand All @@ -516,24 +516,21 @@ static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */

ZVAL_DEREF(arg);

if (smart_str_append_zval(str, arg, EG(exception_string_param_max_len)) == SUCCESS) {
smart_str_appends(str, ", ");
} else {
if (smart_str_append_zval(str, arg, EG(exception_string_param_max_len)) != SUCCESS) {
switch (Z_TYPE_P(arg)) {
case IS_RESOURCE:
smart_str_appends(str, "Resource id #");
smart_str_append_long(str, Z_RES_HANDLE_P(arg));
smart_str_appends(str, ", ");
break;
case IS_ARRAY:
smart_str_appends(str, "Array, ");
smart_str_appends(str, "Array");
break;
case IS_OBJECT: {
zend_string *class_name = Z_OBJ_HANDLER_P(arg, get_class_name)(Z_OBJ_P(arg));
smart_str_appends(str, "Object(");
/* cut off on NULL byte ... class@anonymous */
smart_str_appends(str, ZSTR_VAL(class_name));
smart_str_appends(str, "), ");
smart_str_appends(str, ")");
zend_string_release_ex(class_name, 0);
break;
}
Expand All @@ -542,7 +539,30 @@ static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
}
/* }}} */

static void _build_trace_string(smart_str *str, const HashTable *ht, uint32_t num) /* {{{ */
static void build_trace_args_list(zval *tmp, smart_str *str) /* {{{ */
{
if (UNEXPECTED(Z_TYPE_P(tmp) != IS_ARRAY)) {
/* only happens w/ reflection abuse (Zend/tests/bug63762.phpt) */
zend_error(E_WARNING, "args element is not an array");
return;
}

bool first = true;
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), zend_string *name, zval *arg) {
if (!first) {
smart_str_appends(str, ", ");
}
first = false;
if (name) {
smart_str_append(str, name);
smart_str_appends(str, ": ");
}
build_trace_args(arg, str);
} ZEND_HASH_FOREACH_END();
}
/* }}} */

static void build_trace_string(smart_str *str, const HashTable *ht, uint32_t num) /* {{{ */
{
zval *file, *tmp;

Expand Down Expand Up @@ -588,27 +608,40 @@ static void _build_trace_string(smart_str *str, const HashTable *ht, uint32_t nu
smart_str_appendc(str, '(');
tmp = zend_hash_find_known_hash(ht, ZSTR_KNOWN(ZEND_STR_ARGS));
if (tmp) {
if (EXPECTED(Z_TYPE_P(tmp) == IS_ARRAY)) {
size_t last_len = ZSTR_LEN(str->s);
zend_string *name;
zval *arg;

ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), name, arg) {
if (name) {
smart_str_append(str, name);
smart_str_appends(str, ": ");
}
_build_trace_args(arg, str);
} ZEND_HASH_FOREACH_END();
build_trace_args_list(tmp, str);
}
smart_str_appends(str, ")\n");
}
/* }}} */

if (last_len != ZSTR_LEN(str->s)) {
ZSTR_LEN(str->s) -= 2; /* remove last ', ' */
}
} else {
zend_error(E_WARNING, "args element is not an array");
/* {{{ Gets the function arguments printed as a string from a backtrace frame. */
ZEND_API zend_string *zend_trace_function_args_to_string(const HashTable *frame) {
smart_str str = {0};

zval *tmp = zend_hash_find_known_hash(frame, ZSTR_KNOWN(ZEND_STR_ARGS));
if (tmp) {
build_trace_args_list(tmp, &str);
}

return smart_str_extract(&str);
}
/* }}} */

/* {{{ Gets the currently executing function's arguments as a string. Used by php_verror. */
ZEND_API zend_string *zend_trace_current_function_args_string(void) {
zend_string *dynamic_params = NULL;
/* get a backtrace to snarf function args */
zval backtrace;
zend_fetch_debug_backtrace(&backtrace, /* skip_last */ 0, /* options */ 0, /* limit */ 1);
/* can fail esp if low memory condition */
if (Z_TYPE(backtrace) == IS_ARRAY) {
zval *first_frame = zend_hash_index_find(Z_ARRVAL(backtrace), 0);
if (first_frame) {
dynamic_params = zend_trace_function_args_to_string(Z_ARRVAL_P(first_frame));
}
}
smart_str_appends(str, ")\n");
zval_ptr_dtor(&backtrace);
return dynamic_params;
}
/* }}} */

Expand All @@ -624,7 +657,7 @@ ZEND_API zend_string *zend_trace_to_string(const HashTable *trace, bool include_
continue;
}

_build_trace_string(&str, Z_ARRVAL_P(frame), num++);
build_trace_string(&str, Z_ARRVAL_P(frame), num++);
} ZEND_HASH_FOREACH_END();

if (include_main) {
Expand Down
2 changes: 2 additions & 0 deletions Zend/zend_exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ ZEND_API zend_result zend_update_exception_properties(zend_execute_data *execute
/* show an exception using zend_error(severity,...), severity should be E_ERROR */
ZEND_API ZEND_COLD zend_result zend_exception_error(zend_object *exception, int severity);
ZEND_NORETURN void zend_exception_uncaught_error(const char *prefix, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
ZEND_API zend_string *zend_trace_function_args_to_string(const HashTable *frame);
ZEND_API zend_string *zend_trace_current_function_args_string(void);
ZEND_API zend_string *zend_trace_to_string(const HashTable *trace, bool include_main);

ZEND_API ZEND_COLD zend_object *zend_create_unwind_exit(void);
Expand Down
3 changes: 2 additions & 1 deletion ext/openssl/tests/ServerClientTestCase.inc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ class ServerClientTestCase
$ini = php_ini_loaded_file();
$cmd = sprintf(
'%s %s "%s" %s',
PHP_BINARY, $ini ? "-n -c $ini" : "",
// XXX: TEST_PHP_EXTRA_ARGS for run-test values won't work here?
PHP_BINARY, $ini ? "-n -c $ini -d error_include_args=0" : "",
__FILE__,
WORKER_ARGV_VALUE
);
Expand Down
16 changes: 13 additions & 3 deletions ext/uri/uri_parser_rfc3986.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
struct php_uri_parser_rfc3986_uris {
UriUriA uri;
UriUriA normalized_uri;
unsigned int normalization_mask;
bool normalized_uri_initialized;
};

Expand Down Expand Up @@ -84,12 +85,21 @@ ZEND_ATTRIBUTE_NONNULL static void copy_uri(UriUriA *new_uriparser_uri, const Ur

ZEND_ATTRIBUTE_NONNULL static UriUriA *get_normalized_uri(php_uri_parser_rfc3986_uris *uriparser_uris) {
if (!uriparser_uris->normalized_uri_initialized) {
copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri);
int result = uriNormalizeSyntaxExMmA(&uriparser_uris->normalized_uri, (unsigned int)-1, mm);
ZEND_ASSERT(result == URI_SUCCESS);
int mask_result = uriNormalizeSyntaxMaskRequiredExA(&uriparser_uris->uri, &uriparser_uris->normalization_mask);
ZEND_ASSERT(mask_result == URI_SUCCESS);

if (uriparser_uris->normalization_mask != URI_NORMALIZED) {
copy_uri(&uriparser_uris->normalized_uri, &uriparser_uris->uri);
int result = uriNormalizeSyntaxExMmA(&uriparser_uris->normalized_uri, uriparser_uris->normalization_mask, mm);
ZEND_ASSERT(result == URI_SUCCESS);
}
uriparser_uris->normalized_uri_initialized = true;
}

if (uriparser_uris->normalization_mask == URI_NORMALIZED) {
return &uriparser_uris->uri;
}

return &uriparser_uris->normalized_uri;
}

Expand Down
72 changes: 61 additions & 11 deletions ext/zip/php_zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,12 @@ static char * php_zipobj_get_zip_comment(ze_zip_object *obj, int *len) /* {{{ */
}
/* }}} */

/* Close and free the zip_t */
static bool php_zipobj_close(ze_zip_object *obj) /* {{{ */
/* Close and free the zip_t. If the archive was opened as a string, the
* final contents of the archive will be assigned to *out_str and that
* string will afterwards be owned by the caller.
*
* If out_str is NULL, the final string contents, if any, will be discarded. */
static bool php_zipobj_close(ze_zip_object *obj, zend_string **out_str) /* {{{ */
{
struct zip *intern = obj->za;
bool success = false;
Expand Down Expand Up @@ -606,7 +610,19 @@ static bool php_zipobj_close(ze_zip_object *obj) /* {{{ */
obj->filename_len = 0;
}

if (obj->out_str) {
if (out_str) {
*out_str = obj->out_str;
} else {
zend_string_release(obj->out_str);
}
obj->out_str = NULL;
} else {
ZEND_ASSERT(!out_str);
}

obj->za = NULL;
obj->from_string = false;
return success;
}
/* }}} */
Expand Down Expand Up @@ -1060,7 +1076,7 @@ static void php_zip_object_free_storage(zend_object *object) /* {{{ */
{
ze_zip_object * intern = php_zip_fetch_object(object);

php_zipobj_close(intern);
php_zipobj_close(intern, NULL);

#ifdef HAVE_PROGRESS_CALLBACK
/* if not properly called by libzip */
Expand Down Expand Up @@ -1467,7 +1483,7 @@ PHP_METHOD(ZipArchive, open)
}

/* If we already have an opened zip, free it */
php_zipobj_close(ze_obj);
php_zipobj_close(ze_obj, NULL);

/* open for write without option to empty the archive */
if ((flags & (ZIP_TRUNCATE | ZIP_RDONLY)) == 0) {
Expand All @@ -1491,28 +1507,34 @@ PHP_METHOD(ZipArchive, open)
ze_obj->filename = resolved_path;
ze_obj->filename_len = strlen(resolved_path);
ze_obj->za = intern;
ze_obj->from_string = false;
RETURN_TRUE;
}
/* }}} */

/* {{{ Create new read-only zip using given string */
/* {{{ Create new zip from a string, or a create an empty zip to be saved to a string */
PHP_METHOD(ZipArchive, openString)
{
zend_string *buffer;
zend_string *buffer = NULL;
zend_long flags = 0;
zval *self = ZEND_THIS;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &buffer) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|Sl", &buffer, &flags) == FAILURE) {
RETURN_THROWS();
}

if (!buffer) {
buffer = ZSTR_EMPTY_ALLOC();
}

ze_zip_object *ze_obj = Z_ZIP_P(self);

php_zipobj_close(ze_obj);
php_zipobj_close(ze_obj, NULL);

zip_error_t err;
zip_error_init(&err);

zip_source_t * zip_source = php_zip_create_string_source(buffer, NULL, &err);
zip_source_t * zip_source = php_zip_create_string_source(buffer, &ze_obj->out_str, &err);

if (!zip_source) {
ze_obj->err_zip = zip_error_code_zip(&err);
Expand All @@ -1521,7 +1543,7 @@ PHP_METHOD(ZipArchive, openString)
RETURN_LONG(ze_obj->err_zip);
}

struct zip *intern = zip_open_from_source(zip_source, ZIP_RDONLY, &err);
struct zip *intern = zip_open_from_source(zip_source, flags, &err);
if (!intern) {
ze_obj->err_zip = zip_error_code_zip(&err);
ze_obj->err_sys = zip_error_code_system(&err);
Expand All @@ -1530,6 +1552,7 @@ PHP_METHOD(ZipArchive, openString)
RETURN_LONG(ze_obj->err_zip);
}

ze_obj->from_string = true;
ze_obj->za = intern;
zip_error_fini(&err);
RETURN_TRUE;
Expand Down Expand Up @@ -1568,7 +1591,34 @@ PHP_METHOD(ZipArchive, close)

ZIP_FROM_OBJECT(intern, self);

RETURN_BOOL(php_zipobj_close(Z_ZIP_P(self)));
RETURN_BOOL(php_zipobj_close(Z_ZIP_P(self), NULL));
}
/* }}} */

/* {{{ close the zip archive and get the result as a string */
PHP_METHOD(ZipArchive, closeString)
{
struct zip *intern;
zval *self = ZEND_THIS;

ZEND_PARSE_PARAMETERS_NONE();

ZIP_FROM_OBJECT(intern, self);

if (!Z_ZIP_P(self)->from_string) {
zend_throw_error(NULL, "ZipArchive::closeString can only be called on "
"an archive opened with ZipArchive::openString");
RETURN_THROWS();
}

zend_string *ret = NULL;
bool success = php_zipobj_close(Z_ZIP_P(self), &ret);
ZEND_ASSERT(ret);
if (success) {
RETURN_STR(ret);
}
zend_string_release(ret);
RETURN_FALSE;
}
/* }}} */

Expand Down
2 changes: 2 additions & 0 deletions ext/zip/php_zip.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ typedef struct _ze_zip_object {
HashTable *prop_handler;
char *filename;
size_t filename_len;
zend_string *out_str;
bool from_string;
zip_int64_t last_id;
int err_zip;
int err_sys;
Expand Down
Loading
Loading