@@ -1361,6 +1361,40 @@ PHPAPI zend_off_t _php_stream_tell(const php_stream *stream)
13611361 return stream -> position ;
13621362}
13631363
1364+ static bool php_stream_are_filters_seekable (php_stream_filter * filter , bool is_start_seeking )
1365+ {
1366+ while (filter ) {
1367+ if (filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_NEVER ||
1368+ (!is_start_seeking && filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_START )) {
1369+ php_error_docref (NULL , E_WARNING , "Stream filter %s is not seekable" , filter -> fops -> label );
1370+ return false;
1371+ }
1372+ filter = filter -> next ;
1373+ }
1374+ return true;
1375+ }
1376+
1377+ static zend_result php_stream_filters_seek (php_stream * stream , php_stream_filter * filter , bool is_start_seeking )
1378+ {
1379+ while (filter ) {
1380+ if ((filter -> seekable == PHP_STREAM_FILTER_SEEKABLE_START && is_start_seeking &&
1381+ filter -> feops -> seek (stream , filter , 0 , SEEK_SET ))) {
1382+ php_error_docref (NULL , E_WARNING , "Stream filter seeking for %s failed" , filter -> fops -> label );
1383+ return FAILURE ;
1384+ }
1385+ filter = filter -> next ;
1386+ }
1387+ return SUCCESS ;
1388+ }
1389+
1390+ static zend_result php_stream_filters_seek_all (php_stream * stream , bool is_start_seeking )
1391+ {
1392+ return php_stream_filters_seek (stream , stream -> writefilters .head , is_start_seeking ) == SUCCESS &&
1393+ php_stream_filters_seek (stream , stream -> readfilters .head , is_start_seeking ) == SUCCESS ;
1394+ }
1395+
1396+
1397+
13641398PHPAPI int _php_stream_seek (php_stream * stream , zend_off_t offset , int whence )
13651399{
13661400 if (stream -> fclose_stdiocast == PHP_STREAM_FCLOSE_FOPENCOOKIE ) {
@@ -1373,6 +1407,18 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13731407 }
13741408 }
13751409
1410+ bool is_start_seeking = whence == SEEK_SET && offset == 0 ;
1411+
1412+ if (stream -> writefilters .head ) {
1413+ _php_stream_flush (stream , 0 );
1414+ if (!php_stream_are_filters_seekable (stream -> writefilters .head , is_start_seeking )) {
1415+ return -1 ;
1416+ }
1417+ }
1418+ if (stream -> readfilters .head && !php_stream_are_filters_seekable (stream -> readfilters .head , is_start_seeking )) {
1419+ return -1 ;
1420+ }
1421+
13761422 /* handle the case where we are in the buffer */
13771423 if ((stream -> flags & PHP_STREAM_FLAG_NO_BUFFER ) == 0 ) {
13781424 switch (whence ) {
@@ -1382,6 +1428,7 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13821428 stream -> position += offset ;
13831429 stream -> eof = 0 ;
13841430 stream -> fatal_error = 0 ;
1431+ php_stream_filters_seek_all (stream , is_start_seeking );
13851432 return 0 ;
13861433 }
13871434 break ;
@@ -1392,6 +1439,7 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
13921439 stream -> position = offset ;
13931440 stream -> eof = 0 ;
13941441 stream -> fatal_error = 0 ;
1442+ php_stream_filters_seek_all (stream , is_start_seeking );
13951443 return 0 ;
13961444 }
13971445 break ;
@@ -1401,11 +1449,6 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
14011449
14021450 if (stream -> ops -> seek && (stream -> flags & PHP_STREAM_FLAG_NO_SEEK ) == 0 ) {
14031451 int ret ;
1404-
1405- if (stream -> writefilters .head ) {
1406- _php_stream_flush (stream , 0 );
1407- }
1408-
14091452 switch (whence ) {
14101453 case SEEK_CUR :
14111454 ZEND_ASSERT (stream -> position >= 0 );
@@ -1432,6 +1475,8 @@ PHPAPI int _php_stream_seek(php_stream *stream, zend_off_t offset, int whence)
14321475 /* invalidate the buffer contents */
14331476 stream -> readpos = stream -> writepos = 0 ;
14341477
1478+ php_stream_filters_seek_all (stream , is_start_seeking );
1479+
14351480 return ret ;
14361481 }
14371482 /* else the stream has decided that it can't support seeking after all;
0 commit comments