Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[soon-to-be-rfc] Implement GH-9673: $length argument for fpassthru #10476

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 8 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ PHP 8.3 UPGRADE NOTES
casing only applies to MB_CASE_LOWER and MB_CASE_TITLE modes, not to
MB_CASE_LOWER_SIMPLE and MB_CASE_TITLE_SIMPLE. (Alex Dowad)

- Spl:
. SplFileObject::fpassthru now has an optional $length parameter which allows the user
to specify how many bytes at most may be copied to the output. The behaviour of this
parameter is identical to how the $length parameter of stream_copy_to_stream behaves.

- Standard:
. E_NOTICEs emitted by unserialized() have been promoted to E_WARNING.
RFC: https://wiki.php.net/rfc/improve_unserialize_error_handling
Expand All @@ -73,6 +78,9 @@ PHP 8.3 UPGRADE NOTES
. strtok() raises a warning in the case token is not provided when starting tokenization.
. password_hash() will now chain the underlying Random\RandomException
as the ValueError’s $previous Exception when salt generation fails.
. fpassthru and gzpassthru now has an optional $length parameter which allows the user
to specify how many bytes at most may be copied to the output. The behaviour of this
parameter is identical to how the $length parameter of stream_copy_to_stream behaves.

========================================
6. New Functions
Expand Down
5 changes: 5 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ PHP 8.3 INTERNALS UPGRADE NOTES
for C99 features have been removed and therefore macro definitions
from php_config.h have disappeared. Do not use those feature
macros.
* A new _php_stream_passthru_with_length() function has been added that takes
a stream and a length parameter. This length parameter indicates how many
bytes at most may be written to the output. _php_stream_passthru() is now
a wrapper around _php_stream_passthru_with_length() and still behaves the
same as in the old implementation.

========================
2. Build system changes
Expand Down
14 changes: 11 additions & 3 deletions ext/spl/spl_directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -2552,15 +2552,23 @@ PHP_METHOD(SplFileObject, fgetc)
/* {{{ Output all remaining data from a file pointer */
PHP_METHOD(SplFileObject, fpassthru)
{
zend_long length;
bool length_is_null = true;

spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));

if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
ZEND_PARSE_PARAMETERS_START(0, 1)
Z_PARAM_OPTIONAL
Z_PARAM_LONG_OR_NULL(length, length_is_null)
ZEND_PARSE_PARAMETERS_END();

if (length_is_null) {
length = PHP_STREAM_COPY_ALL;
}

CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);

RETURN_LONG(php_stream_passthru(intern->u.file.stream));
RETURN_LONG(php_stream_passthru_with_length(intern->u.file.stream, length));
} /* }}} */

/* {{{ Implements a mostly ANSI compatible fscanf() */
Expand Down
2 changes: 1 addition & 1 deletion ext/spl/spl_directory.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ public function fseek(int $offset, int $whence = SEEK_SET): int {}
public function fgetc(): string|false {}

/** @tentative-return-type */
public function fpassthru(): int {}
public function fpassthru(?int $length = null): int {}

/** @tentative-return-type */
public function fscanf(string $format, mixed &...$vars): array|int|null {}
Expand Down
6 changes: 4 additions & 2 deletions ext/spl/spl_directory_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
SplFileObject::fpassthru function - functionality test with length
--FILE--
<?php
$obj = New SplFileObject(__DIR__.'/SplFileObject_testinput.csv');
$read = [];
$read[] = $obj->fpassthru(1);
echo "\n";
$read[] = $obj->fpassthru(10);
echo "\n";
$read[] = $obj->fpassthru(0);
echo "\n";
$read[] = $obj->fpassthru(-10000);
echo "\n";
print_r($read);
?>
--EXPECT--
f
irst,secon

d,third
1,2,3
4,5,6
7,8,9
0,0,0

Array
(
[0] => 1
[1] => 10
[2] => 0
[3] => 32
)
2 changes: 1 addition & 1 deletion ext/spl/tests/gh8318.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class bug8318 extends \SplFileObject
{
}

public function fpassthru(): int
public function fpassthru(?int $length = null): int
{
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion ext/standard/basic_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -2650,7 +2650,7 @@ function fopen(string $filename, string $mode, bool $use_include_path = false, $
function fscanf($stream, string $format, mixed &...$vars): array|int|false|null {}

/** @param resource $stream */
function fpassthru($stream): int {}
function fpassthru($stream, ?int $length = null): int {}

/** @param resource $stream */
function ftruncate($stream, int $size): bool {}
Expand Down
3 changes: 2 additions & 1 deletion ext/standard/basic_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions ext/standard/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1253,15 +1253,23 @@ PHPAPI PHP_FUNCTION(fpassthru)
{
zval *res;
size_t size;
zend_long length;
bool length_is_null = true;
php_stream *stream;

ZEND_PARSE_PARAMETERS_START(1, 1)
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_RESOURCE(res)
Z_PARAM_OPTIONAL
Z_PARAM_LONG_OR_NULL(length, length_is_null)
ZEND_PARSE_PARAMETERS_END();

if (length_is_null) {
length = PHP_STREAM_COPY_ALL;
}

PHP_STREAM_FROM_ZVAL(stream, res);

size = php_stream_passthru(stream);
size = php_stream_passthru_with_length(stream, length);
RETURN_LONG(size);
}
/* }}} */
Expand Down
109 changes: 109 additions & 0 deletions ext/standard/tests/file/fpassthru_with_length.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
--TEST--
Test fpassthru() function with length
--FILE--
<?php
$file_name = __DIR__."/passthru_with_length.tmp";
$file_write = fopen($file_name, "w");
fwrite($file_write, "1234567890abcdefghijklmnopqrstuvwxyz");
fclose($file_write);

$file_read = fopen($file_name, "r");

echo "Test consecutive reads\n";
$read = [];
$read[] = fpassthru($file_read, 1);
echo "\n";
$read[] = fpassthru($file_read, 3);
echo "\n";
$read[] = fpassthru($file_read, 0);
echo "\n";
$read[] = fpassthru($file_read, 1);
echo "\n";
$read[] = fpassthru($file_read);
echo "\n";
print_r($read);

echo "Read full file after rewind\n";
rewind($file_read);
fpassthru($file_read);
echo "\n";

echo "Test reading at file offsets\n";
$read = [];
fseek($file_read, 10);
$read[] = fpassthru($file_read, 5);
echo "\n";
fseek($file_read, -5, SEEK_END);
$read[] = fpassthru($file_read, 1);
echo "\n";
fseek($file_read, -3, SEEK_END);
$read[] = fpassthru($file_read, 1000);
echo "\n";
$read[] = fpassthru($file_read);
echo "\n";
print_r($read);

echo "Test reading negative lengths\n";
$read = [];
rewind($file_read);
$read[] = fpassthru($file_read, -1);
echo "\n";
rewind($file_read);
$read[] = fpassthru($file_read, -2);
echo "\n";
rewind($file_read);
$read[] = fpassthru($file_read, -100);
echo "\n";
rewind($file_read);
$read[] = fpassthru($file_read, PHP_INT_MIN);
echo "\n";
print_r($read);

fclose($file_read);
?>
--EXPECT--
Test consecutive reads
1
234

5
67890abcdefghijklmnopqrstuvwxyz
Array
(
[0] => 1
[1] => 3
[2] => 0
[3] => 1
[4] => 31
)
Read full file after rewind
1234567890abcdefghijklmnopqrstuvwxyz
Test reading at file offsets
abcde
v
xyz

Array
(
[0] => 5
[1] => 1
[2] => 3
[3] => 0
)
Test reading negative lengths
1234567890abcdefghijklmnopqrstuvwxyz
1234567890abcdefghijklmnopqrstuvwxyz
1234567890abcdefghijklmnopqrstuvwxyz
1234567890abcdefghijklmnopqrstuvwxyz
Array
(
[0] => 36
[1] => 36
[2] => 36
[3] => 36
)

--CLEAN--
<?php
@unlink(__DIR__."/passthru_with_length.tmp");
?>
17 changes: 17 additions & 0 deletions ext/zlib/tests/gzpassthru_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ $f = __DIR__."/004.txt.gz";
$h = gzopen($f, 'r');
var_dump(gzpassthru($h));
var_dump(gzpassthru($h));
rewind($h);
$result = gzpassthru($h, 10);
echo "\n";
var_dump($result);
$result = gzpassthru($h);
echo "\n";
var_dump($result);
gzclose($h);

?>
Expand All @@ -24,3 +31,13 @@ as it turns around
and I know that it descends down on me
int(176)
int(0)
When you'r
int(10)
e taught through feelings
Destiny flying high above
all I know is that you can realize it
Destiny who cares
as it turns around
and I know that it descends down on me

int(166)
2 changes: 1 addition & 1 deletion ext/zlib/zlib.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ function gzgetc($stream): string|false {}
* @param resource $stream
* @alias fpassthru
*/
function gzpassthru($stream): int {}
function gzpassthru($stream, ?int $length = null): int {}

/**
* @param resource $stream
Expand Down
3 changes: 2 additions & 1 deletion ext/zlib/zlib_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion main/php_streams.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,10 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int
#define php_stream_copy_to_mem(src, maxlen, persistent) _php_stream_copy_to_mem((src), (maxlen), (persistent) STREAMS_CC)

/* output all data from a stream */
PHPAPI ssize_t _php_stream_passthru(php_stream * src STREAMS_DC);
PHPAPI ssize_t _php_stream_passthru(php_stream *src STREAMS_DC);
PHPAPI ssize_t _php_stream_passthru_with_length(php_stream *src, size_t length STREAMS_DC);
#define php_stream_passthru(stream) _php_stream_passthru((stream) STREAMS_CC)
#define php_stream_passthru_with_length(stream, length) _php_stream_passthru_with_length((stream), (length) STREAMS_CC)
END_EXTERN_C()

#include "streams/php_stream_transport.h"
Expand Down
Loading