@@ -1360,6 +1360,40 @@ PHPAPI zend_off_t _php_stream_tell(const php_stream *stream)
13601360 return stream -> position ;
13611361}
13621362
1363+ static bool php_stream_are_filters_seekable (php_stream_filter * filter , bool is_start_seeking )
1364+ {
1365+ while (filter ) {
1366+ if (filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_NEVER ||
1367+ (!is_start_seeking && filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_START )) {
1368+ php_error_docref (NULL , E_WARNING , "Stream filter %s is not seekable" , filter -> fops -> label );
1369+ return false;
1370+ }
1371+ filter = filter -> next ;
1372+ }
1373+ return true;
1374+ }
1375+
1376+ static zend_result php_stream_filters_seek (php_stream * stream , php_stream_filter * filter , bool is_start_seeking )
1377+ {
1378+ while (filter ) {
1379+ if ((filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_START && is_start_seeking &&
1380+ filter -> feops -> seek (stream , filter , 0 , SEEK_SET ))) {
1381+ php_error_docref (NULL , E_WARNING , "Stream filter seeking for %s failed" , filter -> fops -> label );
1382+ return FAILURE ;
1383+ }
1384+ filter = filter -> next ;
1385+ }
1386+ return SUCCESS ;
1387+ }
1388+
1389+ static zend_result php_stream_filters_seek_all (php_stream * stream , bool is_start_seeking )
1390+ {
1391+ return php_stream_filters_seek (stream , stream -> writefilters .head , is_start_seeking ) == SUCCESS &&
1392+ php_stream_filters_seek (stream , stream -> readfilters .head , is_start_seeking ) == SUCCESS ;
1393+ }
1394+
1395+
1396+
13631397PHPAPI int _php_stream_seek (php_stream * stream , zend_off_t offset , int whence )
13641398{
13651399 if (stream -> fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE ) {
@@ -1372,6 +1406,18 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13721406 }
13731407 }
13741408
1409+ bool is_start_seeking = whence == SEEK_SET && offset == 0 ;
1410+
1411+ if (stream -> writefilters .head ) {
1412+ _php_stream_flush (stream , 0 );
1413+ if (!php_stream_are_filters_seekable (stream -> writefilters .head , is_start_seeking )) {
1414+ return -1 ;
1415+ }
1416+ }
1417+ if (stream -> readfilters .head && !php_stream_are_filters_seekable (stream -> readfilters .head , is_start_seeking )) {
1418+ return -1 ;
1419+ }
1420+
13751421 /* handle the case where we are in the buffer */
13761422 if ((stream -> flags & PHP_STREAM_FLAG_NO_BUFFER ) == 0 ) {
13771423 switch (whence ) {
@@ -1381,6 +1427,7 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13811427 stream -> position += offset ;
13821428 stream -> eof = 0 ;
13831429 stream -> fatal_error = 0 ;
1430+ php_stream_filters_seek_all (stream , is_start_seeking );
13841431 return 0 ;
13851432 }
13861433 break ;
@@ -1391,6 +1438,7 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13911438 stream -> position = offset ;
13921439 stream -> eof = 0 ;
13931440 stream -> fatal_error = 0 ;
1441+ php_stream_filters_seek_all (stream , is_start_seeking );
13941442 return 0 ;
13951443 }
13961444 break ;
@@ -1400,11 +1448,6 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
14001448
14011449 if (stream -> ops -> seek && (stream -> flags & PHP_STREAM_FLAG_NO_SEEK ) == 0 ) {
14021450 int ret ;
1403-
1404- if (stream -> writefilters .head ) {
1405- _php_stream_flush (stream , 0 );
1406- }
1407-
14081451 switch (whence ) {
14091452 case SEEK_CUR :
14101453 ZEND_ASSERT (stream -> position >= 0 );
@@ -1431,6 +1474,8 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
14311474 /* invalidate the buffer contents */
14321475 stream -> readpos = stream -> writepos = 0 ;
14331476
1477+ php_stream_filters_seek_all (stream , is_start_seeking );
1478+
14341479 return ret ;
14351480 }
14361481 /* else the stream has decided that it can't support seeking after all;
0 commit comments