@@ -21,6 +21,7 @@ typedef unsigned long z_uintmax_t;
2121#include <stdarg.h>
2222#include <stdlib.h>
2323#include <inttypes.h>
24+ #include <errno.h>
2425
2526#define TESTFILE "/tmp/example.gz"
2627
@@ -94,114 +95,114 @@ static void test_compress(unsigned char *compr, z_uintmax_t comprLen, unsigned c
9495 printf ("uncompress(): %s\n" , (char * )uncompr );
9596}
9697
97- // / * ===========================================================================
98- // * Test read/write of .gz files
99- // */
100- // static void test_gzio(const char *fname, unsigned char *uncompr, z_size_t uncomprLen) {
101- // #ifdef NO_GZCOMPRESS
102- // fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
103- // #else
104- // int err;
105- // size_t read;
106- // size_t len = strlen(hello)+1;
107- // gzFile file;
108- // z_off64_t pos;
109- // z_off64_t comprLen;
110- //
111- // /* Write gz file with test data */
112- // file = PREFIX(gzopen)(fname, "wb");
113- // if (file == NULL)
114- // error("gzopen error\n");
115- // /* Write hello, hello! using gzputs and gzprintf */
116- // PREFIX(gzputc)(file, 'h');
117- // if (PREFIX(gzputs)(file, "ello") != 4)
118- // error("gzputs err: %s\n", PREFIX(gzerror)(file, &err));
119- // if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8)
120- // error("gzprintf err: %s\n", PREFIX(gzerror)(file, &err));
121- // /* Write string null-teriminator using gzseek */
122- // if (PREFIX(gzseek)(file, 1L, SEEK_CUR) < 0)
123- // error("gzseek error, gztell=%ld\n", (long)PREFIX(gztell)(file));
124- // /* Write hello, hello! using gzfwrite using best compression level */
125- // if (PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK)
126- // error("gzsetparams err: %s\n", PREFIX(gzerror)(file, &err));
127- // if (PREFIX(gzfwrite)(hello, len, 1, file) == 0)
128- // error("gzfwrite err: %s\n", PREFIX(gzerror)(file, &err));
129- // /* Flush compressed bytes to file */
130- // if (PREFIX(gzflush)(file, Z_SYNC_FLUSH) != Z_OK)
131- // error("gzflush err: %s\n", PREFIX(gzerror)(file, &err));
132- // comprLen = PREFIX(gzoffset)(file);
133- // if (comprLen <= 0)
134- // error("gzoffset err: %s\n", PREFIX(gzerror)(file, &err));
135- // PREFIX(gzclose)(file);
136- //
137- // /* Open gz file we previously wrote */
138- // file = PREFIX(gzopen)(fname, "rb");
139- // if (file == NULL)
140- // error("gzopen error\n");
141- //
142- // /* Read uncompressed data - hello, hello! string twice */
143- // strcpy((char*)uncompr, "garbages");
144- // if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != (int)(len + len))
145- // error("gzread err: %s\n", PREFIX(gzerror)(file, &err));
146- // if (strcmp((char*)uncompr, hello))
147- // error("bad gzread: %s\n", (char*)uncompr);
148- // else
149- // printf("gzread(): %s\n", (char*)uncompr);
150- // /* Check position at the end of the gz file */
151- // if (PREFIX(gzeof)(file) != 1)
152- // error("gzeof err: not reporting end of stream\n");
153- //
154- // /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */
155- // pos = PREFIX(gzseek)(file, -22L, SEEK_CUR);
156- // if (pos != 6 || PREFIX(gztell)(file) != pos)
157- // error("gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)PREFIX(gztell)(file));
158- // if (PREFIX(gzgetc)(file) != ' ')
159- // error("gzgetc error\n");
160- // if (PREFIX(gzungetc)(' ', file) != ' ')
161- // error("gzungetc error\n");
162- // /* Read first hello, hello! string with gzgets */
163- // strcpy((char*)uncompr, "garbages");
164- // PREFIX(gzgets)(file, (char*)uncompr, (int)uncomprLen);
165- // if (strlen((char*)uncompr) != 7) /* " hello!" */
166- // error("gzgets err after gzseek: %s\n", PREFIX(gzerror)(file, &err));
167- // if (strcmp((char*)uncompr, hello + 6))
168- // error("bad gzgets after gzseek\n");
169- // else
170- // printf("gzgets() after gzseek: %s\n", (char*)uncompr);
171- // /* Seek to second hello, hello! string */
172- // pos = PREFIX(gzseek)(file, 14L, SEEK_SET);
173- // if (pos != 14 || PREFIX(gztell)(file) != pos)
174- // error("gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)PREFIX(gztell)(file));
175- // /* Check position not at end of file */
176- // if (PREFIX(gzeof)(file) != 0)
177- // error("gzeof err: reporting end of stream\n");
178- // /* Read first hello, hello! string with gzfread */
179- // strcpy((char*)uncompr, "garbages");
180- // read = PREFIX(gzfread)(uncompr, uncomprLen, 1, file);
181- // if (strcmp((const char *)uncompr, hello) != 0)
182- // error("bad gzgets\n");
183- // else
184- // printf("gzgets(): %s\n", (char*)uncompr);
185- // pos = PREFIX(gzoffset)(file);
186- // if (pos < 0 || pos != (comprLen + 10))
187- // error("gzoffset err: wrong offset at end\n");
188- // /* Trigger an error and clear it with gzclearerr */
189- // PREFIX(gzfread)(uncompr, (size_t)-1, (size_t)-1, file);
190- // PREFIX(gzerror)(file, &err);
191- // if (err == 0)
192- // error("gzerror err: no error returned\n");
193- // PREFIX(gzclearerr)(file);
194- // PREFIX(gzerror)(file, &err);
195- // if (err != 0)
196- // error("gzclearerr err: not zero %d\n", err);
197- //
198- // PREFIX(gzclose)(file);
199- //
200- // if (PREFIX(gzclose)(NULL) != Z_STREAM_ERROR)
201- // error("gzclose unexpected return when handle null\n");
202- // Z_UNUSED(read);
203- // #endif
204- // }
98+ /* ===========================================================================
99+ * Test read/write of .gz files
100+ */
101+ static void test_gzio (const char * fname , unsigned char * uncompr , z_size_t uncomprLen ) {
102+ #ifdef NO_GZCOMPRESS
103+ fprintf (stderr , "NO_GZCOMPRESS -- gz* functions cannot compress\n" );
104+ #else
105+ int err ;
106+ size_t read ;
107+ size_t len = strlen (hello )+ 1 ;
108+ gzFile file ;
109+ z_off64_t pos ;
110+ z_off64_t comprLen ;
111+
112+ /* Write gz file with test data */
113+ file = PREFIX (gzopen )(fname , "wb" );
114+ if (file == NULL )
115+ error ("gzopen error\n" );
116+ /* Write hello, hello! using gzputs and gzprintf */
117+ PREFIX (gzputc )(file , 'h' );
118+ if (PREFIX (gzputs )(file , "ello" ) != 4 )
119+ error ("gzputs err: %s\n" , PREFIX (gzerror )(file , & err ));
120+ if (PREFIX (gzprintf )(file , ", %s!" , "hello" ) != 8 )
121+ error ("gzprintf err: %s\n" , PREFIX (gzerror )(file , & err ));
122+ /* Write string null-teriminator using gzseek */
123+ if (PREFIX (gzseek )(file , 1L , SEEK_CUR ) < 0 )
124+ error ("gzseek error, gztell=%ld\n" , (long )PREFIX (gztell )(file ));
125+ /* Write hello, hello! using gzfwrite using best compression level */
126+ if (PREFIX (gzsetparams )(file , Z_BEST_COMPRESSION , Z_DEFAULT_STRATEGY ) != Z_OK )
127+ error ("gzsetparams err: %s\n" , PREFIX (gzerror )(file , & err ));
128+ if (PREFIX (gzfwrite )(hello , len , 1 , file ) == 0 )
129+ error ("gzfwrite err: %s\n" , PREFIX (gzerror )(file , & err ));
130+ /* Flush compressed bytes to file */
131+ if (PREFIX (gzflush )(file , Z_SYNC_FLUSH ) != Z_OK )
132+ error ("gzflush err: %s\n" , PREFIX (gzerror )(file , & err ));
133+ comprLen = PREFIX (gzoffset )(file );
134+ if (comprLen <= 0 )
135+ error ("gzoffset err: %s\n" , PREFIX (gzerror )(file , & err ));
136+ PREFIX (gzclose )(file );
137+
138+ /* Open gz file we previously wrote */
139+ file = PREFIX (gzopen )(fname , "rb" );
140+ if (file == NULL )
141+ error ("gzopen error\n" );
142+
143+ /* Read uncompressed data - hello, hello! string twice */
144+ strcpy ((char * )uncompr , "garbages" );
145+ if (PREFIX (gzread )(file , uncompr , (unsigned )uncomprLen ) != (int )(len + len ))
146+ error ("gzread err: %s\n" , PREFIX (gzerror )(file , & err ));
147+ if (strcmp ((char * )uncompr , hello ))
148+ error ("bad gzread: %s\n" , (char * )uncompr );
149+ else
150+ printf ("gzread(): %s\n" , (char * )uncompr );
151+ /* Check position at the end of the gz file */
152+ if (PREFIX (gzeof )(file ) != 1 )
153+ error ("gzeof err: not reporting end of stream\n" );
154+
155+ /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */
156+ pos = PREFIX (gzseek )(file , -22L , SEEK_CUR );
157+ if (pos != 6 || PREFIX (gztell )(file ) != pos )
158+ error ("gzseek error, pos=%ld, gztell=%ld\n" , (long )pos , (long )PREFIX (gztell )(file ));
159+ if (PREFIX (gzgetc )(file ) != ' ' )
160+ error ("gzgetc error\n" );
161+ if (PREFIX (gzungetc )(' ' , file ) != ' ' )
162+ error ("gzungetc error\n" );
163+ /* Read first hello, hello! string with gzgets */
164+ strcpy ((char * )uncompr , "garbages" );
165+ PREFIX (gzgets )(file , (char * )uncompr , (int )uncomprLen );
166+ if (strlen ((char * )uncompr ) != 7 ) /* " hello!" */
167+ error ("gzgets err after gzseek: %s\n" , PREFIX (gzerror )(file , & err ));
168+ if (strcmp ((char * )uncompr , hello + 6 ))
169+ error ("bad gzgets after gzseek\n" );
170+ else
171+ printf ("gzgets() after gzseek: %s\n" , (char * )uncompr );
172+ /* Seek to second hello, hello! string */
173+ pos = PREFIX (gzseek )(file , 14L , SEEK_SET );
174+ if (pos != 14 || PREFIX (gztell )(file ) != pos )
175+ error ("gzseek error, pos=%ld, gztell=%ld\n" , (long )pos , (long )PREFIX (gztell )(file ));
176+ /* Check position not at end of file */
177+ if (PREFIX (gzeof )(file ) != 0 )
178+ error ("gzeof err: reporting end of stream\n" );
179+ /* Read first hello, hello! string with gzfread */
180+ strcpy ((char * )uncompr , "garbages" );
181+ read = PREFIX (gzfread )(uncompr , uncomprLen , 1 , file );
182+ if (strcmp ((const char * )uncompr , hello ) != 0 )
183+ error ("bad gzgets\n" );
184+ else
185+ printf ("gzgets(): %s\n" , (char * )uncompr );
186+ pos = PREFIX (gzoffset )(file );
187+ if (pos < 0 || pos != (comprLen + 10 ))
188+ error ("gzoffset err: wrong offset at end\n" );
189+ /* Trigger an error and clear it with gzclearerr */
190+ PREFIX (gzfread )(uncompr , (size_t )-1 , (size_t )-1 , file );
191+ PREFIX (gzerror )(file , & err );
192+ if (err == 0 )
193+ error ("gzerror err: no error returned\n" );
194+ PREFIX (gzclearerr )(file );
195+ PREFIX (gzerror )(file , & err );
196+ if (err != 0 )
197+ error ("gzclearerr err: not zero %d\n" , err );
198+
199+ PREFIX (gzclose )(file );
200+
201+ if (PREFIX (gzclose )(NULL ) != Z_STREAM_ERROR )
202+ error ("gzclose unexpected return when handle null\n" );
203+ Z_UNUSED (read );
204+ #endif
205+ }
205206
206207/* ===========================================================================
207208 * Test deflate() with small buffers
@@ -957,6 +958,22 @@ static void test_deflate_tune(unsigned char *compr, size_t comprLen) {
957958 CHECK_ERR (err , "deflateEnd" );
958959}
959960
961+ // Tests for a CVE in stock zlib. We're not vulnerable because we exclusively use `vsnprintf`.
962+ void cve_2003_0107 () {
963+ gzFile f ;
964+ int ret ;
965+
966+ f = gzopen ("/dev/null" , "w" );
967+ if (f == NULL ) {
968+ error ("failed to open `/dev/null` for writing\n" );
969+ }
970+
971+ ret = gzprintf (f , "%10240s" , "" );
972+ printf ("gzprintf -> %d\n" , ret );
973+ ret = gzclose (f );
974+ printf ("gzclose -> %d [%d]\n" , ret , errno );
975+ }
976+
960977/* ===========================================================================
961978 * Usage: example [output.gz [input.gz]]
962979 */
@@ -977,8 +994,8 @@ int main(int argc, char *argv[]) {
977994
978995 test_compress (compr , comprLen , uncompr , uncomprLen );
979996
980- // test_gzio((argc > 1 ? argv[1] : TESTFILE),
981- // uncompr, uncomprLen);
997+ test_gzio ((argc > 1 ? argv [1 ] : TESTFILE ),
998+ uncompr , uncomprLen );
982999
9831000 test_deflate (compr , comprLen );
9841001 test_inflate (compr , comprLen , uncompr , uncomprLen );
@@ -1008,6 +1025,8 @@ int main(int argc, char *argv[]) {
10081025 test_deflate_pending (compr , comprLen );
10091026 test_deflate_prime (compr , comprLen , uncompr , uncomprLen );
10101027
1028+ cve_2003_0107 ();
1029+
10111030 free (compr );
10121031 free (uncompr );
10131032
0 commit comments