Skip to content

Commit a2a9873

Browse files
committed
Do not warn that user stream does not implement cast when checking for a cast
1 parent f1bdcca commit a2a9873

File tree

4 files changed

+39
-11
lines changed

4 files changed

+39
-11
lines changed

ext/standard/streamsfuncs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,14 @@ PHP_FUNCTION(stream_socket_pair)
7272
close(pair[0]);
7373
close(pair[1]);
7474
php_error_docref(NULL, E_WARNING, "Failed to open stream from socketpair");
75-
RETURN_FALSE;
75+
RETURN_FALSE;
7676
}
7777
s2 = php_stream_sock_open_from_socket(pair[1], 0);
7878
if (s2 == NULL) {
7979
php_stream_free(s1, PHP_STREAM_FREE_CLOSE);
8080
close(pair[1]);
8181
php_error_docref(NULL, E_WARNING, "Failed to open stream from socketpair");
82-
RETURN_FALSE;
82+
RETURN_FALSE;
8383
}
8484

8585
array_init(return_value);

main/streams/cast.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *resul
187187
}
188188
/* }}} */
189189

190+
static inline bool is_stream_user_stream(const php_stream *stream)
191+
{
192+
return (strlen(stream->ops->label) == strlen("user-space"))
193+
&& strncmp(stream->ops->label, "user-space", strlen("user-space")) == 0;
194+
}
195+
190196
/* {{{ php_stream_cast */
191197
PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show_err)
192198
{
@@ -196,6 +202,10 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
196202
/* synchronize our buffer (if possible) */
197203
if (ret && castas != PHP_STREAM_AS_FD_FOR_SELECT) {
198204
php_stream_flush(stream);
205+
/* Do special handling for user streams as they may not implement the cast method */
206+
if (!show_err && is_stream_user_stream(stream)) {
207+
castas |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
208+
}
199209
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
200210
zend_off_t dummy;
201211

@@ -214,6 +224,11 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
214224
goto exit_success;
215225
}
216226

227+
/* Do special handling for user streams as they may not implement the cast method */
228+
if (!show_err && is_stream_user_stream(stream)) {
229+
castas |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
230+
}
231+
217232
/* if the stream is a stdio stream let's give it a chance to respond
218233
* first, to avoid doubling up the layers of stdio with an fopencookie */
219234
if (php_stream_is(stream, PHP_STREAM_IS_STDIO) &&
@@ -299,8 +314,14 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
299314
php_error_docref(NULL, E_WARNING, "Cannot cast a filtered stream on this system");
300315
}
301316
return FAILURE;
302-
} else if (stream->ops->cast && stream->ops->cast(stream, castas, ret) == SUCCESS) {
303-
goto exit_success;
317+
} else if (stream->ops->cast) {
318+
/* Do special handling for user streams as they may not implement the cast method */
319+
if (!show_err && is_stream_user_stream(stream)) {
320+
castas |= PHP_STREAM_FLAG_SUPPRESS_ERRORS;
321+
}
322+
if (stream->ops->cast(stream, castas, ret) == SUCCESS) {
323+
goto exit_success;
324+
}
304325
}
305326

306327
if (show_err) {

main/streams/userspace.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,8 @@ static int php_userstreamop_rewinddir(php_stream *stream, zend_off_t offset, int
13731373

13741374
}
13751375

1376+
/* The user stream overloads the castas parameter by accepting PHP_STREAM_FLAG_SUPPRESS_ERRORS as a bitmask
1377+
* If present the call is silent, otherwise it will report errors */
13761378
static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
13771379
{
13781380
php_userstream_data_t *us = (php_userstream_data_t *)stream->abstract;
@@ -1382,6 +1384,8 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
13821384
php_stream * intstream = NULL;
13831385
int call_result;
13841386
int ret = FAILURE;
1387+
bool report_errors = !(castas & PHP_STREAM_FLAG_SUPPRESS_ERRORS);
1388+
castas &= ~PHP_STREAM_FLAG_SUPPRESS_ERRORS;
13851389

13861390
ZVAL_STRINGL(&func_name, USERSTREAM_CAST, sizeof(USERSTREAM_CAST)-1);
13871391

@@ -1398,22 +1402,28 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr)
13981402

13991403
do {
14001404
if (call_result == FAILURE) {
1401-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
1405+
if (report_errors) {
1406+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " is not implemented!",
14021407
ZSTR_VAL(us->wrapper->ce->name));
1408+
}
14031409
break;
14041410
}
14051411
if (!zend_is_true(&retval)) {
14061412
break;
14071413
}
14081414
php_stream_from_zval_no_verify(intstream, &retval);
14091415
if (!intstream) {
1410-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
1416+
if (report_errors) {
1417+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must return a stream resource",
14111418
ZSTR_VAL(us->wrapper->ce->name));
1419+
}
14121420
break;
14131421
}
14141422
if (intstream == stream) {
1415-
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
1423+
if (report_errors) {
1424+
php_error_docref(NULL, E_WARNING, "%s::" USERSTREAM_CAST " must not return itself",
14161425
ZSTR_VAL(us->wrapper->ce->name));
1426+
}
14171427
intstream = NULL;
14181428
break;
14191429
}

tests/output/stream_isatty_non_castable_userwrapper.phpt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,5 @@ $fd = fopen("test://foo","r");
1818
var_dump(stream_isatty($fd));
1919

2020
?>
21-
--EXPECTF--
22-
Warning: stream_isatty(): test_wrapper::stream_cast is not implemented! in %s on line %d
23-
24-
Warning: stream_isatty(): test_wrapper::stream_cast is not implemented! in %s on line %d
21+
--EXPECT--
2522
bool(false)

0 commit comments

Comments
 (0)