From 0b814ee33d3e845323b795c804a76f93462eb051 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:32:58 +0000 Subject: [PATCH 1/8] main: Add a custom Fast ZPP specifier for php_streams --- main/php_streams.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/main/php_streams.h b/main/php_streams.h index 33b14ff4eb3df..80cb96951ee14 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -286,6 +286,35 @@ END_EXTERN_C() #define php_stream_from_zval_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2_ex((pzval), "stream", php_file_le_stream(), php_file_le_pstream()) BEGIN_EXTERN_C() + +static zend_always_inline bool php_stream_zend_parse_arg_into_stream(zval *arg, php_stream **destination_stream_ptr, bool check_null) +{ + if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) { + *destination_stream_ptr = (php_stream*)zend_fetch_resource2(Z_RES_P(arg), "stream", php_file_le_stream(), php_file_le_pstream()); + if (UNEXPECTED(*destination_stream_ptr == NULL)) { + return false; + } + } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + *destination_stream_ptr = NULL; + } else { + return false; + } + return true; +} + +#define PHP_Z_PARAM_STREAM_EX(destination_stream_ptr, check_null) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (UNEXPECTED(!php_stream_zend_parse_arg_into_stream(_arg, &destination_stream_ptr, check_null))) { \ + _error_code = ZPP_ERROR_FAILURE; \ + if (!EG(exception)) { \ + _expected_type = check_null ? Z_EXPECTED_RESOURCE_OR_NULL : Z_EXPECTED_RESOURCE; \ + _error_code = ZPP_ERROR_WRONG_ARG; \ + } \ + break; \ + } +#define PHP_Z_PARAM_STREAM(dest) PHP_Z_PARAM_STREAM_EX(dest, false) +#define PHP_Z_PARAM_STREAM_OR_NULL(dest) PHP_Z_PARAM_STREAM_EX(dest, true) + PHPAPI php_stream *php_stream_encloses(php_stream *enclosing, php_stream *enclosed); #define php_stream_free_enclosed(stream_enclosed, close_options) _php_stream_free_enclosed((stream_enclosed), (close_options)) PHPAPI int _php_stream_free_enclosed(php_stream *stream_enclosed, int close_options); From 0239ef4b64e57df5b7e775f9ab7ba536eb5be090 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:33:40 +0000 Subject: [PATCH 2/8] ext/standard: Use new php_streams fast ZPP specifier for file functions Fix a corresponding test --- ext/standard/file.c | 101 ++++++---------------------- ext/standard/tests/file/fwrite.phpt | 14 +++- 2 files changed, 32 insertions(+), 83 deletions(-) diff --git a/ext/standard/file.c b/ext/standard/file.c index 01f49640e4af6..908aee85a2e74 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -102,10 +102,6 @@ php_file_globals file_globals; /* }}} */ -#define PHP_STREAM_FROM_ZVAL(stream, arg) \ - ZEND_ASSERT(Z_TYPE_P(arg) == IS_RESOURCE); \ - php_stream_from_res(stream, Z_RES_P(arg)); - /* {{{ ZTS-stuff / Globals / Prototypes */ /* sharing globals is *evil* */ @@ -215,19 +211,17 @@ PHPAPI void php_flock_common(php_stream *stream, zend_long operation, /* {{{ Portable file locking */ PHP_FUNCTION(flock) { - zval *res, *wouldblock = NULL; + zval *wouldblock = NULL; php_stream *stream; zend_long operation = 0; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(operation) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(wouldblock) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - php_flock_common(stream, operation, 2, wouldblock, return_value); } /* }}} */ @@ -756,15 +750,12 @@ PHP_FUNCTION(fopen) /* {{{ Close an open file pointer */ PHPAPI PHP_FUNCTION(fclose) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if ((stream->flags & PHP_STREAM_FLAG_NO_FCLOSE) != 0) { php_error_docref(NULL, E_WARNING, ZEND_LONG_FMT " is not a valid stream resource", stream->res->handle); RETURN_FALSE; @@ -836,15 +827,12 @@ PHP_FUNCTION(popen) /* {{{ Close a file pointer opened by popen() */ PHP_FUNCTION(pclose) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - FG(pclose_wait) = 1; zend_list_close(stream->res); FG(pclose_wait) = 0; @@ -855,15 +843,12 @@ PHP_FUNCTION(pclose) /* {{{ Test for end-of-file on a file pointer */ PHPAPI PHP_FUNCTION(feof) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (php_stream_eof(stream)) { RETURN_TRUE; } else { @@ -875,7 +860,6 @@ PHPAPI PHP_FUNCTION(feof) /* {{{ Get a line from file pointer */ PHPAPI PHP_FUNCTION(fgets) { - zval *res; zend_long len = 1024; bool len_is_null = 1; char *buf = NULL; @@ -884,13 +868,11 @@ PHPAPI PHP_FUNCTION(fgets) php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(len, len_is_null) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (len_is_null) { /* ask streams to give us a buffer of an appropriate size */ buf = php_stream_get_line(stream, NULL, 0, &line_len); @@ -926,15 +908,12 @@ PHPAPI PHP_FUNCTION(fgets) /* {{{ Get a character from file pointer */ PHPAPI PHP_FUNCTION(fgetc) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - int result = php_stream_getc(stream); if (result == EOF) { @@ -989,7 +968,6 @@ PHP_FUNCTION(fscanf) /* {{{ Binary-safe file write */ PHPAPI PHP_FUNCTION(fwrite) { - zval *res; char *input; size_t inputlen; ssize_t ret; @@ -999,7 +977,7 @@ PHPAPI PHP_FUNCTION(fwrite) php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(input, inputlen) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) @@ -1017,8 +995,6 @@ PHPAPI PHP_FUNCTION(fwrite) RETURN_LONG(0); } - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_write(stream, input, num_bytes); if (ret < 0) { RETURN_FALSE; @@ -1031,16 +1007,13 @@ PHPAPI PHP_FUNCTION(fwrite) /* {{{ Flushes output */ PHPAPI PHP_FUNCTION(fflush) { - zval *res; int ret; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_flush(stream); if (ret) { RETURN_FALSE; @@ -1052,15 +1025,12 @@ PHPAPI PHP_FUNCTION(fflush) /* {{{ Rewind the position of a file pointer */ PHPAPI PHP_FUNCTION(rewind) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (-1 == php_stream_rewind(stream)) { RETURN_FALSE; } @@ -1071,16 +1041,13 @@ PHPAPI PHP_FUNCTION(rewind) /* {{{ Get file pointer's read/write position */ PHPAPI PHP_FUNCTION(ftell) { - zval *res; zend_long ret; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - ret = php_stream_tell(stream); if (ret == -1) { RETURN_FALSE; @@ -1092,19 +1059,16 @@ PHPAPI PHP_FUNCTION(ftell) /* {{{ Seek on a file pointer */ PHPAPI PHP_FUNCTION(fseek) { - zval *res; zend_long offset, whence = SEEK_SET; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL Z_PARAM_LONG(whence) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - RETURN_LONG(php_stream_seek(stream, offset, (int) whence)); } /* }}} */ @@ -1215,16 +1179,13 @@ PHP_FUNCTION(umask) /* {{{ Output all remaining data from a file pointer */ PHPAPI PHP_FUNCTION(fpassthru) { - zval *res; size_t size; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - size = php_stream_passthru(stream); RETURN_LONG(size); } @@ -1303,15 +1264,12 @@ PHP_FUNCTION(unlink) PHP_FUNCTION(fsync) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (!php_stream_sync_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't fsync this stream!"); RETURN_FALSE; @@ -1322,15 +1280,12 @@ PHP_FUNCTION(fsync) PHP_FUNCTION(fdatasync) { - zval *res; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (!php_stream_sync_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't fsync this stream!"); RETURN_FALSE; @@ -1342,12 +1297,11 @@ PHP_FUNCTION(fdatasync) /* {{{ Truncate file to 'size' length */ PHP_FUNCTION(ftruncate) { - zval *fp; zend_long size; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(size) ZEND_PARSE_PARAMETERS_END(); @@ -1356,8 +1310,6 @@ PHP_FUNCTION(ftruncate) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fp); - if (!php_stream_truncate_supported(stream)) { php_error_docref(NULL, E_WARNING, "Can't truncate this stream!"); RETURN_FALSE; @@ -1441,15 +1393,12 @@ PHPAPI void php_fstat(php_stream *stream, zval *return_value) /* {{{ Stat() on a filehandle */ PHP_FUNCTION(fstat) { - zval *fp; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, fp); - php_fstat(stream, return_value); } /* }}} */ @@ -1588,18 +1537,15 @@ PHPAPI zend_result php_copy_file_ctx(const char *src, const char *dest, int src_ /* {{{ Binary-safe file read */ PHPAPI PHP_FUNCTION(fread) { - zval *res; zend_long len; php_stream *stream; zend_string *str; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(res) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(len) ZEND_PARSE_PARAMETERS_END(); - PHP_STREAM_FROM_ZVAL(stream, res); - if (len <= 0) { zend_argument_value_error(2, "must be greater than 0"); RETURN_THROWS(); @@ -1683,7 +1629,7 @@ PHP_FUNCTION(fputcsv) char delimiter = ','; /* allow this to be set as parameter */ char enclosure = '"'; /* allow this to be set as parameter */ php_stream *stream; - zval *fp = NULL, *fields = NULL; + zval *fields = NULL; ssize_t ret; char *delimiter_str = NULL, *enclosure_str = NULL; zend_string *escape_str = NULL; @@ -1691,7 +1637,7 @@ PHP_FUNCTION(fputcsv) zend_string *eol_str = NULL; ZEND_PARSE_PARAMETERS_START(2, 6) - Z_PARAM_RESOURCE(fp) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_ARRAY(fields) Z_PARAM_OPTIONAL Z_PARAM_STRING(delimiter_str, delimiter_str_len) @@ -1725,8 +1671,6 @@ PHP_FUNCTION(fputcsv) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fp); - ret = php_fputcsv(stream, fields, delimiter, enclosure, escape_char, eol_str); if (ret < 0) { RETURN_FALSE; @@ -1811,7 +1755,6 @@ PHP_FUNCTION(fgetcsv) char *buf; php_stream *stream; - zval *fd; bool len_is_null = 1; char *delimiter_str = NULL; size_t delimiter_str_len = 0; @@ -1820,7 +1763,7 @@ PHP_FUNCTION(fgetcsv) zend_string *escape_str = NULL; ZEND_PARSE_PARAMETERS_START(1, 5) - Z_PARAM_RESOURCE(fd) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(len, len_is_null) Z_PARAM_STRING(delimiter_str, delimiter_str_len) @@ -1861,8 +1804,6 @@ PHP_FUNCTION(fgetcsv) RETURN_THROWS(); } - PHP_STREAM_FROM_ZVAL(stream, fd); - if (len < 0) { if ((buf = php_stream_get_line(stream, NULL, 0, &buf_len)) == NULL) { RETURN_FALSE; diff --git a/ext/standard/tests/file/fwrite.phpt b/ext/standard/tests/file/fwrite.phpt index 90e158d048a6c..1494ea7a0f5e8 100644 --- a/ext/standard/tests/file/fwrite.phpt +++ b/ext/standard/tests/file/fwrite.phpt @@ -17,13 +17,21 @@ var_dump(fwrite($fp, "data", -1)); var_dump(fwrite($fp, "data", 100000)); fclose($fp); -var_dump(fwrite($fp, "data", -1)); +try { + var_dump(fwrite($fp, "data", -1)); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), PHP_EOL; +} var_dump(file_get_contents($filename)); -@unlink($filename); echo "Done\n"; ?> +--CLEAN-- + --EXPECTF-- int(0) @@ -31,6 +39,6 @@ Notice: fwrite(): Write of 4 bytes failed with errno=9 Bad file descriptor in %s bool(false) int(0) int(4) -int(0) +TypeError: fwrite(): supplied resource is not a valid stream resource string(4) "data" Done From 5bf7259428d4145be3547592c184af2532b98e13 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:43:17 +0000 Subject: [PATCH 3/8] ext/standard: Use new php_streams fast ZPP specifier for stream functions --- ext/standard/streamsfuncs.c | 104 ++++++++---------------------------- 1 file changed, 22 insertions(+), 82 deletions(-) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 4f9a7106c01c1..818a645086b05 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -265,11 +265,10 @@ PHP_FUNCTION(stream_socket_accept) php_timeout_ull conv; struct timeval tv; php_stream *stream = NULL, *clistream = NULL; - zval *zstream; zend_string *errstr = NULL; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_DOUBLE_OR_NULL(timeout, timeout_is_null) Z_PARAM_ZVAL(zpeername) @@ -282,8 +281,6 @@ PHP_FUNCTION(stream_socket_accept) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - /* prepare the timeout value for use */ struct timeval *tv_pointer; if (timeout < 0.0 || timeout >= (double) PHP_TIMEOUT_ULL_MAX / 1000000.0) { @@ -328,17 +325,14 @@ PHP_FUNCTION(stream_socket_accept) PHP_FUNCTION(stream_socket_get_name) { php_stream *stream; - zval *zstream; bool want_peer; zend_string *name = NULL; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(want_peer) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (0 != php_stream_xport_get_name(stream, want_peer, &name, NULL, NULL @@ -359,7 +353,6 @@ PHP_FUNCTION(stream_socket_get_name) PHP_FUNCTION(stream_socket_sendto) { php_stream *stream; - zval *zstream; zend_long flags = 0; char *data, *target_addr = NULL; size_t datalen, target_addr_len = 0; @@ -367,13 +360,12 @@ PHP_FUNCTION(stream_socket_sendto) socklen_t sl = 0; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(data, datalen) Z_PARAM_OPTIONAL Z_PARAM_LONG(flags) Z_PARAM_STRING(target_addr, target_addr_len) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); if (target_addr_len) { /* parse the address */ @@ -391,7 +383,7 @@ PHP_FUNCTION(stream_socket_sendto) PHP_FUNCTION(stream_socket_recvfrom) { php_stream *stream; - zval *zstream, *zremote = NULL; + zval *zremote = NULL; zend_string *remote_addr = NULL; zend_long to_read = 0; zend_string *read_buf; @@ -399,15 +391,13 @@ PHP_FUNCTION(stream_socket_recvfrom) int recvd; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(to_read) Z_PARAM_OPTIONAL Z_PARAM_LONG(flags) Z_PARAM_ZVAL(zremote) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (zremote) { ZEND_TRY_ASSIGN_REF_NULL(zremote); } @@ -441,13 +431,12 @@ PHP_FUNCTION(stream_socket_recvfrom) PHP_FUNCTION(stream_get_contents) { php_stream *stream; - zval *zsrc; zend_long maxlen, desiredpos = -1L; bool maxlen_is_null = 1; zend_string *contents; ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) Z_PARAM_LONG(desiredpos) @@ -460,8 +449,6 @@ PHP_FUNCTION(stream_get_contents) RETURN_THROWS(); } - php_stream_from_zval(stream, zsrc); - if (desiredpos >= 0) { int seek_res = 0; zend_off_t position; @@ -494,15 +481,14 @@ PHP_FUNCTION(stream_get_contents) PHP_FUNCTION(stream_copy_to_stream) { php_stream *src, *dest; - zval *zsrc, *zdest; zend_long maxlen, pos = 0; bool maxlen_is_null = 1; size_t len; int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zsrc) - Z_PARAM_RESOURCE(zdest) + PHP_Z_PARAM_STREAM(src) + PHP_Z_PARAM_STREAM(dest) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(maxlen, maxlen_is_null) Z_PARAM_LONG(pos) @@ -512,9 +498,6 @@ PHP_FUNCTION(stream_copy_to_stream) maxlen = PHP_STREAM_COPY_ALL; } - php_stream_from_zval(src, zsrc); - php_stream_from_zval(dest, zdest); - if (pos > 0 && php_stream_seek(src, pos, SEEK_SET) < 0) { php_error_docref(NULL, E_WARNING, "Failed to seek to position " ZEND_LONG_FMT " in the stream", pos); RETURN_FALSE; @@ -532,15 +515,12 @@ PHP_FUNCTION(stream_copy_to_stream) /* {{{ Retrieves header/meta data from streams/file pointers */ PHP_FUNCTION(stream_get_meta_data) { - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - array_init(return_value); if (!php_stream_populate_meta_data(stream, return_value)) { @@ -1235,7 +1215,6 @@ PHP_FUNCTION(stream_context_create) /* {{{ streams filter functions */ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) { - zval *zstream; php_stream *stream; char *filtername; size_t filternamelen; @@ -1245,15 +1224,13 @@ static void apply_filter_to_stream(int append, INTERNAL_FUNCTION_PARAMETERS) int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(filtername, filternamelen) Z_PARAM_OPTIONAL Z_PARAM_LONG(read_write) Z_PARAM_ZVAL(filterparams) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if ((read_write & PHP_STREAM_FILTER_ALL) == 0) { /* Chain not specified. * Examine stream->mode to determine which filters are needed @@ -1358,12 +1335,11 @@ PHP_FUNCTION(stream_get_line) char *str = NULL; size_t str_len = 0; zend_long max_length; - zval *zstream; zend_string *buf; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(max_length) Z_PARAM_OPTIONAL Z_PARAM_STRING(str, str_len) @@ -1377,8 +1353,6 @@ PHP_FUNCTION(stream_get_line) max_length = PHP_SOCK_CHUNK_SIZE; } - php_stream_from_zval(stream, zstream); - if ((buf = php_stream_get_record(stream, max_length, str, str_len))) { RETURN_STR(buf); } else { @@ -1391,17 +1365,14 @@ PHP_FUNCTION(stream_get_line) /* {{{ Set blocking/non-blocking mode on a socket or stream */ PHP_FUNCTION(stream_set_blocking) { - zval *zstream; bool block; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(block) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (php_stream_set_option(stream, PHP_STREAM_OPTION_BLOCKING, block, NULL) == -1) { RETURN_FALSE; } @@ -1415,21 +1386,18 @@ PHP_FUNCTION(stream_set_blocking) #if defined(HAVE_SYS_TIME_H) || defined(PHP_WIN32) PHP_FUNCTION(stream_set_timeout) { - zval *socket; zend_long seconds, microseconds = 0; struct timeval t; php_stream *stream; int argc = ZEND_NUM_ARGS(); ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_RESOURCE(socket) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(seconds) Z_PARAM_OPTIONAL Z_PARAM_LONG(microseconds) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, socket); - #ifdef PHP_WIN32 t.tv_sec = (long)seconds; @@ -1462,19 +1430,16 @@ PHP_FUNCTION(stream_set_timeout) /* {{{ Set file write buffer */ PHP_FUNCTION(stream_set_write_buffer) { - zval *arg1; int ret; zend_long arg2; size_t buff; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - buff = arg2; /* if buff is 0 then set to non-buffered */ @@ -1493,11 +1458,10 @@ PHP_FUNCTION(stream_set_chunk_size) { int ret; zend_long csize; - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(csize) ZEND_PARSE_PARAMETERS_END(); @@ -1514,8 +1478,6 @@ PHP_FUNCTION(stream_set_chunk_size) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - ret = php_stream_set_option(stream, PHP_STREAM_OPTION_SET_CHUNK_SIZE, (int)csize, NULL); RETURN_LONG(ret > 0 ? (zend_long)ret : (zend_long)EOF); @@ -1525,19 +1487,16 @@ PHP_FUNCTION(stream_set_chunk_size) /* {{{ Set file read buffer */ PHP_FUNCTION(stream_set_read_buffer) { - zval *arg1; int ret; zend_long arg2; size_t buff; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(arg2) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - buff = arg2; /* if buff is 0 then set to non-buffered */ @@ -1555,21 +1514,18 @@ PHP_FUNCTION(stream_set_read_buffer) PHP_FUNCTION(stream_socket_enable_crypto) { zend_long cryptokind = 0; - zval *zstream, *zsessstream = NULL; php_stream *stream, *sessstream = NULL; bool enable, cryptokindnull = 1; int ret; ZEND_PARSE_PARAMETERS_START(2, 4) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_BOOL(enable) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(cryptokind, cryptokindnull) - Z_PARAM_RESOURCE_OR_NULL(zsessstream) + PHP_Z_PARAM_STREAM_OR_NULL(sessstream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); - if (enable) { if (cryptokindnull) { zval *val; @@ -1582,10 +1538,6 @@ PHP_FUNCTION(stream_socket_enable_crypto) cryptokind = Z_LVAL_P(val); } - if (zsessstream) { - php_stream_from_zval(sessstream, zsessstream); - } - if (php_stream_xport_crypto_setup(stream, cryptokind, sessstream) < 0) { RETURN_FALSE; } @@ -1658,14 +1610,11 @@ PHP_FUNCTION(stream_is_local) PHP_FUNCTION(stream_supports_lock) { php_stream *stream; - zval *zsrc; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - if (!php_stream_supports_lock(stream)) { RETURN_FALSE; } @@ -1676,16 +1625,13 @@ PHP_FUNCTION(stream_supports_lock) /* {{{ Check if a stream is a TTY. */ PHP_FUNCTION(stream_isatty) { - zval *zsrc; php_stream *stream; php_socket_t fileno; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - /* get the fd. * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag when casting. * It is only used here so that the buffered data warning is not displayed. @@ -1718,19 +1664,16 @@ PHP_FUNCTION(stream_isatty) */ PHP_FUNCTION(sapi_windows_vt100_support) { - zval *zsrc; php_stream *stream; bool enable, enable_is_null = 1; zend_long fileno; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(zsrc) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_OPTIONAL Z_PARAM_BOOL_OR_NULL(enable, enable_is_null) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zsrc); - /* get the fd. * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag when casting. * It is only used here so that the buffered data warning is not displayed. @@ -1785,11 +1728,10 @@ PHP_FUNCTION(sapi_windows_vt100_support) PHP_FUNCTION(stream_socket_shutdown) { zend_long how; - zval *zstream; php_stream *stream; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_RESOURCE(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(how) ZEND_PARSE_PARAMETERS_END(); @@ -1800,8 +1742,6 @@ PHP_FUNCTION(stream_socket_shutdown) RETURN_THROWS(); } - php_stream_from_zval(stream, zstream); - RETURN_BOOL(php_stream_xport_shutdown(stream, (stream_shutdown_t)how) == 0); } /* }}} */ From f4f01626c653b56e34fad70aef7b762842f6dc63 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:57:44 +0000 Subject: [PATCH 4/8] ext/standard: Use new php_streams fast ZPP specifier --- ext/standard/formatted_print.c | 14 +++++--------- ext/standard/user_filters.c | 5 ++--- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index 8d8c09f443c04..9471ad3c7ba23 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -860,18 +860,16 @@ PHP_FUNCTION(fprintf) php_stream *stream; char *format; size_t format_len; - zval *arg1, *args; - int argc; + zval *args = NULL; + int argc = 0; zend_string *result; ZEND_PARSE_PARAMETERS_START(2, -1) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(format, format_len) Z_PARAM_VARIADIC('*', args, argc) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - result = php_formatted_print(format, format_len, args, argc, 2); if (result == NULL) { RETURN_THROWS(); @@ -890,19 +888,17 @@ PHP_FUNCTION(vfprintf) php_stream *stream; char *format; size_t format_len; - zval *arg1, *args; + zval *args; zend_array *array; int argc; zend_string *result; ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_RESOURCE(arg1) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(format, format_len) Z_PARAM_ARRAY_HT(array) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, arg1); - args = php_formatted_print_get_array(array, &argc); result = php_formatted_print(format, format_len, args, argc, -1); diff --git a/ext/standard/user_filters.c b/ext/standard/user_filters.c index 2168fbce0af34..88facf1e137f2 100644 --- a/ext/standard/user_filters.c +++ b/ext/standard/user_filters.c @@ -439,7 +439,7 @@ PHP_FUNCTION(stream_bucket_append) /* {{{ Create a new bucket for use on the current stream */ PHP_FUNCTION(stream_bucket_new) { - zval *zstream, zbucket; + zval zbucket; php_stream *stream; char *buffer; char *pbuffer; @@ -447,11 +447,10 @@ PHP_FUNCTION(stream_bucket_new) php_stream_bucket *bucket; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_ZVAL(zstream) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_STRING(buffer, buffer_len) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, zstream); pbuffer = pemalloc(buffer_len, php_stream_is_persistent(stream)); memcpy(pbuffer, buffer, buffer_len); From 4263efc2b14423622c416aea9ee90029bc6e1923 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:38:14 +0000 Subject: [PATCH 5/8] ext/ftp: Use new php_streams fast ZPP specifier --- ext/ftp/php_ftp.c | 60 +++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 0336f9e953773..17dc94b728eba 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -566,7 +566,7 @@ PHP_FUNCTION(ftp_systype) /* {{{ Retrieves a file from the FTP server and writes it to an open file */ PHP_FUNCTION(ftp_fget) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; @@ -574,11 +574,16 @@ PHP_FUNCTION(ftp_fget) size_t file_len; zend_long mode=FTPTYPE_IMAGE, resumepos=0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_STRING(file, file_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(resumepos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -610,7 +615,7 @@ PHP_FUNCTION(ftp_fget) /* {{{ Retrieves a file from the FTP server asynchronly and writes it to an open file */ PHP_FUNCTION(ftp_nb_fget) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; php_stream *stream; @@ -618,11 +623,16 @@ PHP_FUNCTION(ftp_nb_fget) size_t file_len; zend_long mode=FTPTYPE_IMAGE, resumepos=0, ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ors|ll", &z_ftp, php_ftp_ce, &z_file, &file, &file_len, &mode, &resumepos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_STRING(file, file_len) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(resumepos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -848,7 +858,7 @@ PHP_FUNCTION(ftp_nb_continue) /* {{{ Stores a file from an open file to the FTP server */ PHP_FUNCTION(ftp_fput) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; size_t remote_len; @@ -856,11 +866,16 @@ PHP_FUNCTION(ftp_fput) php_stream *stream; char *remote; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + Z_PARAM_STRING(remote, remote_len) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(startpos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_zval(stream, z_file); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ @@ -895,7 +910,7 @@ PHP_FUNCTION(ftp_fput) /* {{{ Stores a file from an open file to the FTP server nbronly */ PHP_FUNCTION(ftp_nb_fput) { - zval *z_ftp, *z_file; + zval *z_ftp; ftpbuf_t *ftp; ftptype_t xtype; size_t remote_len; @@ -904,11 +919,16 @@ PHP_FUNCTION(ftp_nb_fput) php_stream *stream; char *remote; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osr|ll", &z_ftp, php_ftp_ce, &remote, &remote_len, &z_file, &mode, &startpos) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 5) + Z_PARAM_OBJECT_OF_CLASS(z_ftp, php_ftp_ce) + Z_PARAM_STRING(remote, remote_len) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(mode) + Z_PARAM_LONG(startpos) + ZEND_PARSE_PARAMETERS_END(); + GET_FTPBUF(ftp, z_ftp); - php_stream_from_res(stream, Z_RES_P(z_file)); XTYPE(xtype, mode); /* ignore autoresume if autoseek is switched off */ From f9672b844b5f498d977eabe1e29bf6f7a948e6f2 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:52:27 +0000 Subject: [PATCH 6/8] ext/pgsql: Use new php_streams fast ZPP specifier --- ext/pgsql/pgsql.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index b1a1dfb49a7ac..036fc5c0572a1 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -6265,22 +6265,19 @@ PHP_FUNCTION(pg_put_copy_end) PHP_FUNCTION(pg_socket_poll) { - zval *z_socket; php_stream *stream; php_socket_t socket; zend_long read, write; zend_long ts = -1; ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_RESOURCE(z_socket) + PHP_Z_PARAM_STREAM(stream) Z_PARAM_LONG(read) Z_PARAM_LONG(write) Z_PARAM_OPTIONAL Z_PARAM_LONG(ts) ZEND_PARSE_PARAMETERS_END(); - php_stream_from_zval(stream, z_socket); - if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void **)&socket, 0)) { zend_argument_type_error(1, "invalid resource socket"); RETURN_THROWS(); From fefa65a123f0df77740d7571a4815a9252b13741 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:54:51 +0000 Subject: [PATCH 7/8] ext/hash: Use new php_streams fast ZPP specifier --- ext/hash/hash.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 5579aeb978e3c..13c345de4dd1c 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -707,18 +707,20 @@ PHP_FUNCTION(hash_update) /* {{{ Pump data into the hashing algorithm from an open stream */ PHP_FUNCTION(hash_update_stream) { - zval *zhash, *zstream; + zend_object *hash_obj; php_hashcontext_object *hash; php_stream *stream = NULL; zend_long length = -1, didread = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Or|l", &zhash, php_hashcontext_ce, &zstream, &length) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_OBJ_OF_CLASS(hash_obj, php_hashcontext_ce) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(length) + ZEND_PARSE_PARAMETERS_END(); - hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); + hash = php_hashcontext_from_object(hash_obj); PHP_HASHCONTEXT_VERIFY(hash); - php_stream_from_zval(stream, zstream); while (length) { char buf[1024]; From cb07bd3f0204f3a5debe8ddcea94a676f3fdfcc3 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 3 Mar 2025 15:59:55 +0000 Subject: [PATCH 8/8] ext/bz2: Use new php_streams fast ZPP specifier --- ext/bz2/bz2.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index d95a4d5036800..9ed5342a7df8f 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -303,16 +303,15 @@ static PHP_MINFO_FUNCTION(bz2) /* {{{ Reads up to length bytes from a BZip2 stream, or 1024 bytes if length is not specified */ PHP_FUNCTION(bzread) { - zval *bz; zend_long len = 1024; php_stream *stream; zend_string *data; - if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &bz, &len)) { - RETURN_THROWS(); - } - - php_stream_from_zval(stream, bz); + ZEND_PARSE_PARAMETERS_START(1, 2) + PHP_Z_PARAM_STREAM(stream) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(len) + ZEND_PARSE_PARAMETERS_END(); if (len < 0) { zend_argument_value_error(2, "must be greater than or equal to 0"); @@ -563,17 +562,14 @@ PHP_FUNCTION(bzdecompress) The central error handling interface, does the work for bzerrno, bzerrstr and bzerror */ static void php_bz2_error(INTERNAL_FUNCTION_PARAMETERS, int opt) { - zval *bzp; /* BZip2 Resource Pointer */ php_stream *stream; const char *errstr; /* Error string */ int errnum; /* Error number */ struct php_bz2_stream_data_t *self; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &bzp) == FAILURE) { - RETURN_THROWS(); - } - - php_stream_from_zval(stream, bzp); + ZEND_PARSE_PARAMETERS_START(1, 1) + PHP_Z_PARAM_STREAM(stream) + ZEND_PARSE_PARAMETERS_END(); if (!php_stream_is(stream, PHP_STREAM_IS_BZIP2)) { zend_argument_type_error(1, "must be a bz2 stream");