@@ -8,6 +8,7 @@ typedef ssize_t stream_ret_t;
88typedef struct {
99 zval arch_zv ;
1010 uint32_t generation ;
11+ la_int64_t remaining_bytes ; /* bytes left to read, or -1 if entry size is not set */
1112} arch_stream_data ;
1213
1314static stream_ret_t php_arch_ops_write (php_stream * stream , const char * buf ,
@@ -58,13 +59,28 @@ static stream_ret_t php_arch_ops_read(php_stream *stream, char *buf,
5859 return 0 ;
5960 }
6061
62+ // Cap reads at the declared entry size
63+ arch_stream_data * data = stream -> abstract ;
64+ if (data -> remaining_bytes >= 0 ) {
65+ if (data -> remaining_bytes == 0 ) {
66+ return 0 ; /* EOF */
67+ }
68+ if ((la_int64_t )count > data -> remaining_bytes ) {
69+ count = (size_t )data -> remaining_bytes ;
70+ }
71+ }
72+
6173 la_ssize_t read = archive_read_data (arch , buf , count );
6274 if (read < 0 ) {
6375 php_error_docref (NULL , E_WARNING , "Error reading data: %s [%d]" ,
6476 archive_error_string (arch ), archive_errno (arch ));
6577 return STREAM_ERR_RET ;
6678 }
6779
80+ if (data -> remaining_bytes >= 0 ) {
81+ data -> remaining_bytes -= read ;
82+ }
83+
6884 return (stream_ret_t )read ;
6985}
7086
@@ -106,6 +122,13 @@ static int php_arch_ops_seek(php_stream *stream, zend_off_t offset, int whence,
106122 }
107123
108124 * newoffset = (zend_off_t )res ;
125+ arch_stream_data * data = stream -> abstract ;
126+ if (data -> remaining_bytes >= 0 ) {
127+ la_int64_t entry_size = arch_object_from_zv (& data -> arch_zv )-> current_entry_size ;
128+ if (entry_size >= 0 ) {
129+ data -> remaining_bytes = entry_size - res ;
130+ }
131+ }
109132 return 0 ; // SUCCESS
110133}
111134
@@ -122,7 +145,9 @@ php_stream *php_stream_arch_cur_entry_stream(zval *nonnull arch_zv)
122145{
123146 arch_stream_data * data = emalloc (sizeof (* data ));
124147 ZVAL_COPY (& data -> arch_zv , arch_zv );
125- data -> generation = arch_object_from_zv (arch_zv )-> entry_generation ;
148+ arch_object * obj = arch_object_from_zv (arch_zv );
149+ data -> generation = obj -> entry_generation ;
150+ data -> remaining_bytes = obj -> current_entry_size ; /* -1 if not set */
126151 php_stream * stream =
127152 php_stream_alloc (& php_stream_arch_ops , data , NULL , "rb" );
128153 return stream ;
0 commit comments