Skip to content

Commit db06fcf

Browse files
committed
Add tests for uncastable streams and dataloss streams
Moreover, stop using php_stream_can_cast() just before a php_stream_cast()
1 parent 4cee2c0 commit db06fcf

15 files changed

+591
-38
lines changed

ext/gd/gd.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,11 +1562,9 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
15621562
pefree(pstr, 1);
15631563
zend_string_release_ex(buff, 0);
15641564
}
1565-
else if (php_stream_can_cast(stream, PHP_STREAM_AS_STDIO)) {
1566-
/* try and force the stream to be FILE* */
1567-
if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) {
1568-
goto out_err;
1569-
}
1565+
/* try and force the stream to be FILE* */
1566+
else if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO | PHP_STREAM_CAST_TRY_HARD, (void **) &fp, REPORT_ERRORS)) {
1567+
goto out_err;
15701568
}
15711569

15721570
if (!im && fp) {
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
--TEST--
2+
imagecreatefrompng(): uncastable user stream
3+
--EXTENSIONS--
4+
gd
5+
--XFAIL--
6+
Script hangs for unknown reason
7+
--SKIPIF--
8+
<?php
9+
if (!GD_BUNDLED) die("skip requires bundled GD library\n");
10+
?>
11+
--FILE--
12+
<?php
13+
14+
class DummyStreamWrapper
15+
{
16+
/** @var resource|null */
17+
public $context;
18+
19+
/** @var resource|null */
20+
public $handle;
21+
22+
public function stream_cast(int $castAs)
23+
{
24+
return false;
25+
}
26+
27+
public function stream_close(): void { }
28+
29+
public function stream_open(string $path, string $mode, int $options = 0, ?string &$openedPath = null): bool
30+
{
31+
return true;
32+
}
33+
34+
public function stream_read(int $count)
35+
{
36+
return 0;
37+
}
38+
39+
public function stream_seek(int $offset, int $whence = SEEK_SET): bool
40+
{
41+
return true;
42+
}
43+
44+
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
45+
{
46+
return false;
47+
}
48+
49+
public function stream_stat()
50+
{
51+
return [];
52+
}
53+
54+
public function stream_tell()
55+
{
56+
return [];
57+
}
58+
59+
public function stream_truncate(int $newSize): bool
60+
{
61+
return true;
62+
}
63+
64+
public function stream_write(string $data) { }
65+
66+
67+
public function unlink(string $path): bool
68+
{
69+
return false;
70+
}
71+
}
72+
stream_wrapper_register('custom', DummyStreamWrapper::class);
73+
74+
$fp = fopen("custom://myvar", "r+");
75+
76+
/* This tests the underlying _php_image_create_from() C function */
77+
//var_dump(imagecreatefrompng("custom://myvar"));
78+
fclose($fp);
79+
80+
echo "Done";
81+
?>
82+
--EXPECTF--
83+
Warning: imagecreatefrompng(): Could not use stream of type 'user-space' in %s on line %d
84+
bool(false)
85+
Done
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
imagecreatefrompng(): casting stream emits data loss
3+
--EXTENSIONS--
4+
gd
5+
--SKIPIF--
6+
<?php
7+
if (!GD_BUNDLED) die("skip requires bundled GD library\n");
8+
//if (getenv('SKIP_ONLINE_TESTS')) die('skip online test');
9+
require __DIR__ . '/../../standard/tests/http/server.inc'; http_server_skipif();
10+
?>
11+
--INI--
12+
allow_url_fopen=1
13+
--FILE--
14+
<?php
15+
16+
require __DIR__ . '/../../standard/tests/http/server.inc';
17+
18+
$responses = array(
19+
"data://text/plain,HTTP/1.0 200 Ok\r\nSome: Header\r\nSome: Header\r\n\r\nBody",
20+
);
21+
22+
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
23+
24+
$handle = fopen($uri, 'r');
25+
/* This tests the underlying _php_image_create_from() C function */
26+
var_dump(imagecreatefrompng($uri));
27+
var_dump(fread($handle, 20));
28+
fclose($handle);
29+
30+
http_server_kill($pid);
31+
?>
32+
--EXPECTF--
33+
Warning: imagecreatefrompng(%s): Failed to open stream: %s! in %s on line %d
34+
bool(false)
35+
string(4) "Body"

ext/posix/posix.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,10 @@ static int php_posix_stream_get_fd(zval *zfp, int *fd) /* {{{ */
426426
if (stream == NULL) {
427427
return 0;
428428
}
429-
if (php_stream_can_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT) == SUCCESS) {
430-
php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)fd, 0);
431-
} else if (php_stream_can_cast(stream, PHP_STREAM_AS_FD) == SUCCESS) {
432-
php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)fd, 0);
433-
} else {
429+
if (
430+
php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT, (void*)&fd, 0) == FAILURE &&
431+
php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0) == FAILURE
432+
) {
434433
php_error_docref(NULL, E_WARNING, "Could not use stream of type '%s'",
435434
stream->ops->label);
436435
return 0;

ext/posix/tests/posix_isatty.phpt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,11 @@
22
posix_isatty(): Basic tests
33
--EXTENSIONS--
44
posix
5-
--SKIPIF--
6-
<?php
7-
if (!function_exists('posix_isatty')) die('skip posix_isatty() not found');
8-
?>
95
--FILE--
106
<?php
117

12-
var_dump(posix_isatty(0));
8+
var_dump(posix_isatty(STDIN));
139

1410
?>
15-
--EXPECTF--
16-
bool(%s)
11+
--EXPECT--
12+
bool(false)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
--TEST--
2+
posix_isatty(): uncastable user stream
3+
--EXTENSIONS--
4+
posix
5+
--FILE--
6+
<?php
7+
class DummyStreamWrapper
8+
{
9+
/** @var resource|null */
10+
public $context;
11+
12+
/** @var resource|null */
13+
public $handle;
14+
15+
public function stream_cast(int $castAs)
16+
{
17+
return false;
18+
}
19+
20+
public function stream_close(): void { }
21+
22+
public function stream_open(string $path, string $mode, int $options = 0, ?string &$openedPath = null): bool
23+
{
24+
return true;
25+
}
26+
27+
public function stream_read(int $count)
28+
{
29+
return 0;
30+
}
31+
32+
public function stream_seek(int $offset, int $whence = SEEK_SET): bool
33+
{
34+
return true;
35+
}
36+
37+
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
38+
{
39+
return false;
40+
}
41+
42+
public function stream_stat()
43+
{
44+
return [];
45+
}
46+
47+
public function stream_tell()
48+
{
49+
return [];
50+
}
51+
52+
public function stream_truncate(int $newSize): bool
53+
{
54+
return true;
55+
}
56+
57+
public function stream_write(string $data) { }
58+
59+
60+
public function unlink(string $path): bool
61+
{
62+
return false;
63+
}
64+
}
65+
stream_wrapper_register('custom', DummyStreamWrapper::class);
66+
67+
$fp = fopen("custom://myvar", "r+");
68+
var_dump(posix_isatty($fp));
69+
fclose($fp);
70+
71+
echo "Done";
72+
?>
73+
--EXPECTF--
74+
Warning: posix_isatty(): Could not use stream of type 'user-space' in %s on line %d
75+
bool(false)
76+
Done
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
posix_isatty(): casting stream emits data loss
3+
--EXTENSIONS--
4+
posix
5+
--SKIPIF--
6+
<?php
7+
//if (getenv('SKIP_ONLINE_TESTS')) die('skip online test');
8+
require __DIR__ . '/../../standard/tests/http/server.inc'; http_server_skipif();
9+
?>
10+
--INI--
11+
allow_url_fopen=1
12+
--FILE--
13+
<?php
14+
15+
require __DIR__ . '/../../standard/tests/http/server.inc';
16+
17+
$responses = array(
18+
"data://text/plain,HTTP/1.0 200 Ok\r\nSome: Header\r\nSome: Header\r\n\r\nBody",
19+
);
20+
21+
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
22+
23+
$handle = fopen($uri, 'r');
24+
var_dump(posix_isatty($handle));
25+
var_dump(fread($handle, 20));
26+
fclose($handle);
27+
28+
http_server_kill($pid);
29+
?>
30+
--EXPECTF--
31+
Warning: posix_isatty(): %d bytes of buffered data lost during stream conversion! in %s on line %d
32+
bool(false)
33+
string(4) "Body"
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
--TEST--
2+
posix_ttyname(): uncastable user stream
3+
--EXTENSIONS--
4+
posix
5+
--FILE--
6+
<?php
7+
class DummyStreamWrapper
8+
{
9+
/** @var resource|null */
10+
public $context;
11+
12+
/** @var resource|null */
13+
public $handle;
14+
15+
public function stream_cast(int $castAs)
16+
{
17+
return false;
18+
}
19+
20+
public function stream_close(): void { }
21+
22+
public function stream_open(string $path, string $mode, int $options = 0, ?string &$openedPath = null): bool
23+
{
24+
return true;
25+
}
26+
27+
public function stream_read(int $count)
28+
{
29+
return 0;
30+
}
31+
32+
public function stream_seek(int $offset, int $whence = SEEK_SET): bool
33+
{
34+
return true;
35+
}
36+
37+
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
38+
{
39+
return false;
40+
}
41+
42+
public function stream_stat()
43+
{
44+
return [];
45+
}
46+
47+
public function stream_tell()
48+
{
49+
return [];
50+
}
51+
52+
public function stream_truncate(int $newSize): bool
53+
{
54+
return true;
55+
}
56+
57+
public function stream_write(string $data) { }
58+
59+
60+
public function unlink(string $path): bool
61+
{
62+
return false;
63+
}
64+
}
65+
stream_wrapper_register('custom', DummyStreamWrapper::class);
66+
67+
$fp = fopen("custom://myvar", "r+");
68+
var_dump(posix_ttyname($fp));
69+
fclose($fp);
70+
71+
echo "Done";
72+
?>
73+
--EXPECTF--
74+
Warning: posix_ttyname(): Could not use stream of type 'user-space' in %s on line %d
75+
bool(false)
76+
Done
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
posix_ttyname(): casting stream emits data loss
3+
--EXTENSIONS--
4+
posix
5+
--SKIPIF--
6+
<?php
7+
//if (getenv('SKIP_ONLINE_TESTS')) die('skip online test');
8+
require __DIR__ . '/../../standard/tests/http/server.inc'; http_server_skipif();
9+
?>
10+
--INI--
11+
allow_url_fopen=1
12+
--FILE--
13+
<?php
14+
15+
require __DIR__ . '/../../standard/tests/http/server.inc';
16+
17+
$responses = array(
18+
"data://text/plain,HTTP/1.0 200 Ok\r\nSome: Header\r\nSome: Header\r\n\r\nBody",
19+
);
20+
21+
['pid' => $pid, 'uri' => $uri] = http_server($responses, $output);
22+
23+
$handle = fopen($uri, 'r');
24+
var_dump(posix_ttyname($handle));
25+
var_dump(fread($handle, 20));
26+
fclose($handle);
27+
28+
http_server_kill($pid);
29+
?>
30+
--EXPECTF--
31+
Warning: posix_ttyname(): %d bytes of buffered data lost during stream conversion! in %s on line %d
32+
bool(false)
33+
string(4) "Body"

0 commit comments

Comments
 (0)