Code

zlib: zlib can only process 4GB at a time
[git.git] / zlib.c
1 /*
2  * zlib wrappers to make sure we don't silently miss errors
3  * at init time.
4  */
5 #include "cache.h"
7 static const char *zerr_to_string(int status)
8 {
9         switch (status) {
10         case Z_MEM_ERROR:
11                 return "out of memory";
12         case Z_VERSION_ERROR:
13                 return "wrong version";
14         case Z_NEED_DICT:
15                 return "needs dictionary";
16         case Z_DATA_ERROR:
17                 return "data stream error";
18         case Z_STREAM_ERROR:
19                 return "stream consistency error";
20         default:
21                 return "unknown error";
22         }
23 }
25 /*
26  * avail_in and avail_out in zlib are counted in uInt, which typically
27  * limits the size of the buffer we can use to 4GB when interacting
28  * with zlib in a single call to inflate/deflate.
29  */
30 #define ZLIB_BUF_MAX ((uInt)-1)
31 static inline uInt zlib_buf_cap(unsigned long len)
32 {
33         if (ZLIB_BUF_MAX < len)
34                 die("working buffer for zlib too large");
35         return len;
36 }
38 static void zlib_pre_call(git_zstream *s)
39 {
40         s->z.next_in = s->next_in;
41         s->z.next_out = s->next_out;
42         s->z.total_in = s->total_in;
43         s->z.total_out = s->total_out;
44         s->z.avail_in = zlib_buf_cap(s->avail_in);
45         s->z.avail_out = zlib_buf_cap(s->avail_out);
46 }
48 static void zlib_post_call(git_zstream *s)
49 {
50         s->next_in = s->z.next_in;
51         s->next_out = s->z.next_out;
52         s->total_in = s->z.total_in;
53         s->total_out = s->z.total_out;
54         s->avail_in = s->z.avail_in;
55         s->avail_out = s->z.avail_out;
56 }
58 void git_inflate_init(git_zstream *strm)
59 {
60         int status;
62         zlib_pre_call(strm);
63         status = inflateInit(&strm->z);
64         zlib_post_call(strm);
65         if (status == Z_OK)
66                 return;
67         die("inflateInit: %s (%s)", zerr_to_string(status),
68             strm->z.msg ? strm->z.msg : "no message");
69 }
71 void git_inflate_init_gzip_only(git_zstream *strm)
72 {
73         /*
74          * Use default 15 bits, +16 is to accept only gzip and to
75          * yield Z_DATA_ERROR when fed zlib format.
76          */
77         const int windowBits = 15 + 16;
78         int status;
80         zlib_pre_call(strm);
81         status = inflateInit2(&strm->z, windowBits);
82         zlib_post_call(strm);
83         if (status == Z_OK)
84                 return;
85         die("inflateInit2: %s (%s)", zerr_to_string(status),
86             strm->z.msg ? strm->z.msg : "no message");
87 }
89 void git_inflate_end(git_zstream *strm)
90 {
91         int status;
93         zlib_pre_call(strm);
94         status = inflateEnd(&strm->z);
95         zlib_post_call(strm);
96         if (status == Z_OK)
97                 return;
98         error("inflateEnd: %s (%s)", zerr_to_string(status),
99               strm->z.msg ? strm->z.msg : "no message");
102 int git_inflate(git_zstream *strm, int flush)
104         int status;
106         zlib_pre_call(strm);
107         status = inflate(&strm->z, flush);
108         zlib_post_call(strm);
109         switch (status) {
110         /* Z_BUF_ERROR: normal, needs more space in the output buffer */
111         case Z_BUF_ERROR:
112         case Z_OK:
113         case Z_STREAM_END:
114                 return status;
116         case Z_MEM_ERROR:
117                 die("inflate: out of memory");
118         default:
119                 break;
120         }
121         error("inflate: %s (%s)", zerr_to_string(status),
122               strm->z.msg ? strm->z.msg : "no message");
123         return status;
126 #if defined(NO_DEFLATE_BOUND) || ZLIB_VERNUM < 0x1200
127 #define deflateBound(c,s)  ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
128 #endif
130 unsigned long git_deflate_bound(git_zstream *strm, unsigned long size)
132         return deflateBound(&strm->z, size);
135 void git_deflate_init(git_zstream *strm, int level)
137         int status;
139         zlib_pre_call(strm);
140         status = deflateInit(&strm->z, level);
141         zlib_post_call(strm);
142         if (status == Z_OK)
143                 return;
144         die("deflateInit: %s (%s)", zerr_to_string(status),
145             strm->z.msg ? strm->z.msg : "no message");
148 void git_deflate_init_gzip(git_zstream *strm, int level)
150         /*
151          * Use default 15 bits, +16 is to generate gzip header/trailer
152          * instead of the zlib wrapper.
153          */
154         const int windowBits = 15 + 16;
155         int status;
157         zlib_pre_call(strm);
158         status = deflateInit2(&strm->z, level,
159                                   Z_DEFLATED, windowBits,
160                                   8, Z_DEFAULT_STRATEGY);
161         zlib_post_call(strm);
162         if (status == Z_OK)
163                 return;
164         die("deflateInit2: %s (%s)", zerr_to_string(status),
165             strm->z.msg ? strm->z.msg : "no message");
168 void git_deflate_end(git_zstream *strm)
170         int status;
172         zlib_pre_call(strm);
173         status = deflateEnd(&strm->z);
174         zlib_post_call(strm);
175         if (status == Z_OK)
176                 return;
177         error("deflateEnd: %s (%s)", zerr_to_string(status),
178               strm->z.msg ? strm->z.msg : "no message");
181 int git_deflate_end_gently(git_zstream *strm)
183         int status;
185         zlib_pre_call(strm);
186         status = deflateEnd(&strm->z);
187         zlib_post_call(strm);
188         return status;
191 int git_deflate(git_zstream *strm, int flush)
193         int status;
195         zlib_pre_call(strm);
196         status = deflate(&strm->z, flush);
197         zlib_post_call(strm);
198         switch (status) {
199         /* Z_BUF_ERROR: normal, needs more space in the output buffer */
200         case Z_BUF_ERROR:
201         case Z_OK:
202         case Z_STREAM_END:
203                 return status;
205         case Z_MEM_ERROR:
206                 die("deflate: out of memory");
207         default:
208                 break;
209         }
210         error("deflate: %s (%s)", zerr_to_string(status),
211               strm->z.msg ? strm->z.msg : "no message");
212         return status;