Skip to content

Commit 088e269

Browse files
committed
MFB: Bunch of streams related fixes.
1 parent 4474f92 commit 088e269

File tree

5 files changed

+31
-17
lines changed

5 files changed

+31
-17
lines changed

ext/standard/file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2384,7 +2384,7 @@ PHPAPI int php_copy_file(char *src, char *dest TSRMLS_DC)
23842384
int ret = FAILURE;
23852385

23862386
srcstream = php_stream_open_wrapper(src, "rb",
2387-
ENFORCE_SAFE_MODE | REPORT_ERRORS,
2387+
STREAM_DISABLE_OPEN_BASEDIR | REPORT_ERRORS,
23882388
NULL);
23892389

23902390
if (!srcstream) {

main/php_streams.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
406406
/* this flag is used when only the headers from HTTP request are to be fetched */
407407
#define STREAM_ONLY_GET_HEADERS 512
408408

409+
/* don't apply open_basedir checks */
410+
#define STREAM_DISABLE_OPEN_BASEDIR 1024
411+
409412
/* Antique - no longer has meaning */
410413
#define IGNORE_URL_WIN 0
411414

main/streams/cast.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,12 @@ PHPAPI int _php_stream_cast(php_stream *stream, int castas, void **ret, int show
208208
return FAILURE;
209209
#endif
210210

211-
if (flags & PHP_STREAM_CAST_TRY_HARD) {
211+
if (!php_stream_is_filtered(stream) && stream->ops->cast && stream->ops->cast(stream, castas, NULL TSRMLS_CC) == SUCCESS) {
212+
if (FAILURE == stream->ops->cast(stream, castas, ret TSRMLS_CC)) {
213+
return FAILURE;
214+
}
215+
goto exit_success;
216+
} else if (flags & PHP_STREAM_CAST_TRY_HARD) {
212217
php_stream *newstream;
213218

214219
newstream = php_stream_fopen_tmpfile();

main/streams/plain_wrapper.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, char
603603
DIR *dir = NULL;
604604
php_stream *stream = NULL;
605605

606-
if (php_check_open_basedir(path TSRMLS_CC)) {
606+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(path TSRMLS_CC)) {
607607
return NULL;
608608
}
609609

@@ -637,7 +637,7 @@ static php_stream *php_plain_files_stream_opener(php_stream_wrapper *wrapper, ch
637637
return php_stream_fopen_with_path_rel(path, mode, PG(include_path), opened_path, options);
638638
}
639639

640-
if (php_check_open_basedir(path TSRMLS_CC)) {
640+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(path TSRMLS_CC)) {
641641
return NULL;
642642
}
643643

@@ -702,7 +702,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
702702
}
703703

704704

705-
if (php_check_open_basedir(filename TSRMLS_CC)) {
705+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(filename TSRMLS_CC)) {
706706
return NULL;
707707
}
708708

@@ -722,7 +722,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
722722
/* Absolute path open */
723723
if (IS_ABSOLUTE_PATH(filename, filename_length)) {
724724

725-
if (php_check_open_basedir(filename TSRMLS_CC)) {
725+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(filename TSRMLS_CC)) {
726726
return NULL;
727727
}
728728

@@ -748,7 +748,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
748748

749749
free(cwd);
750750

751-
if (php_check_open_basedir(trypath TSRMLS_CC)) {
751+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(trypath TSRMLS_CC)) {
752752
return NULL;
753753
}
754754
if ((php_check_safe_mode_include_dir(trypath TSRMLS_CC)) == 0) {
@@ -764,7 +764,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
764764

765765
if (!path || (path && !*path)) {
766766

767-
if (php_check_open_basedir(path TSRMLS_CC)) {
767+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(path TSRMLS_CC)) {
768768
return NULL;
769769
}
770770

@@ -809,7 +809,7 @@ PHPAPI php_stream *_php_stream_fopen_with_path(char *filename, char *mode, char
809809
}
810810
snprintf(trypath, MAXPATHLEN, "%s/%s", ptr, filename);
811811

812-
if (php_check_open_basedir(trypath TSRMLS_CC)) {
812+
if ((options & STREAM_DISABLE_OPEN_BASEDIR == 0) && php_check_open_basedir(trypath TSRMLS_CC)) {
813813
stream = NULL;
814814
goto stream_done;
815815
}

main/streams/streams.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,16 @@ static size_t _php_stream_write_buffer(php_stream *stream, const char *buf, size
801801
{
802802
size_t didwrite = 0, towrite, justwrote;
803803

804+
/* if we have a seekable stream we need to ensure that data is written at the
805+
* current stream->position. This means invalidating the read buffer and then
806+
* performing a low-level seek */
807+
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
808+
stream->readpos = stream->writepos = 0;
809+
810+
stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position TSRMLS_CC);
811+
}
812+
813+
804814
while (count > 0) {
805815
towrite = count;
806816
if (towrite > stream->chunk_size)
@@ -817,8 +827,6 @@ static size_t _php_stream_write_buffer(php_stream *stream, const char *buf, size
817827
* buffered from fifos and sockets */
818828
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0 && !php_stream_is_filtered(stream)) {
819829
stream->position += justwrote;
820-
stream->writepos = 0;
821-
stream->readpos = 0;
822830
}
823831
} else {
824832
break;
@@ -947,10 +955,6 @@ PHPAPI off_t _php_stream_tell(php_stream *stream TSRMLS_DC)
947955

948956
PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_DC)
949957
{
950-
/* not moving anywhere */
951-
if ((offset == 0 && whence == SEEK_CUR) || (offset == stream->position && whence == SEEK_SET))
952-
return 0;
953-
954958
/* handle the case where we are in the buffer */
955959
if ((stream->flags & PHP_STREAM_FLAG_NO_BUFFER) == 0) {
956960
switch(whence) {
@@ -974,8 +978,6 @@ PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_
974978
}
975979
}
976980

977-
/* invalidate the buffer contents */
978-
stream->readpos = stream->writepos = 0;
979981

980982
if (stream->ops->seek && (stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) {
981983
int ret;
@@ -995,6 +997,10 @@ PHPAPI int _php_stream_seek(php_stream *stream, off_t offset, int whence TSRMLS_
995997
if (((stream->flags & PHP_STREAM_FLAG_NO_SEEK) == 0) || ret == 0) {
996998
if (ret == 0)
997999
stream->eof = 0;
1000+
1001+
/* invalidate the buffer contents */
1002+
stream->readpos = stream->writepos = 0;
1003+
9981004
return ret;
9991005
}
10001006
/* else the stream has decided that it can't support seeking after all;

0 commit comments

Comments
 (0)