@@ -33,24 +33,55 @@ struct php_gz_stream_data_t {
3333static ssize_t php_gziop_read (php_stream * stream , char * buf , size_t count )
3434{
3535 struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t * ) stream -> abstract ;
36- int read ;
36+ ssize_t total_read = 0 ;
37+
38+ /* Despite the count argument of gzread() being "unsigned int",
39+ * the return value is "int". Error returns are values < 0, otherwise the count is returned.
40+ * To properly distinguish error values from success value, we therefore need to cap at INT_MAX.
41+ */
42+ do {
43+ unsigned int chunk_size = MIN (count , INT_MAX );
44+ int read = gzread (self -> gz_file , buf , chunk_size );
45+ count -= chunk_size ;
46+
47+ if (gzeof (self -> gz_file )) {
48+ stream -> eof = 1 ;
49+ }
3750
38- /* XXX this needs to be looped for the case count > UINT_MAX */
39- read = gzread (self -> gz_file , buf , count );
51+ if (UNEXPECTED (read < 0 )) {
52+ return read ;
53+ }
4054
41- if ( gzeof ( self -> gz_file )) {
42- stream -> eof = 1 ;
43- }
55+ total_read += read ;
56+ buf += read ;
57+ } while ( count > 0 && ! stream -> eof );
4458
45- return read ;
59+ return total_read ;
4660}
4761
4862static ssize_t php_gziop_write (php_stream * stream , const char * buf , size_t count )
4963{
5064 struct php_gz_stream_data_t * self = (struct php_gz_stream_data_t * ) stream -> abstract ;
65+ ssize_t total_written = 0 ;
66+
67+ /* Despite the count argument of gzread() being "unsigned int",
68+ * the return value is "int". Error returns are values < 0, otherwise the count is returned.
69+ * To properly distinguish error values from success value, we therefore need to cap at INT_MAX.
70+ */
71+ do {
72+ unsigned int chunk_size = MIN (count , INT_MAX );
73+ int written = gzwrite (self -> gz_file , buf , chunk_size );
74+ count -= chunk_size ;
75+
76+ if (UNEXPECTED (written < 0 )) {
77+ return written ;
78+ }
79+
80+ total_written += written ;
81+ buf += written ;
82+ } while (count > 0 );
5183
52- /* XXX this needs to be looped for the case count > UINT_MAX */
53- return gzwrite (self -> gz_file , (char * ) buf , count );
84+ return total_written ;
5485}
5586
5687static int php_gziop_seek (php_stream * stream , zend_off_t offset , int whence , zend_off_t * newoffs )
0 commit comments