1 /* inflate_p.h -- Private inline functions and macros shared with more than one deflate method
2 *
3 */
4
5 #ifndef INFLATE_P_H
6 #define INFLATE_P_H
7
8 #include <stdlib.h>
9
10 /* Architecture-specific hooks. */
11 #ifdef S390_DFLTCC_INFLATE
12 # include "arch/s390/dfltcc_inflate.h"
13 #else
14 /* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */
15 # define ZALLOC_INFLATE_STATE(strm) ((struct inflate_state *)ZALLOC(strm, 1, sizeof(struct inflate_state)))
16 # define ZFREE_STATE(strm, addr) ZFREE(strm, addr)
17 # define ZCOPY_INFLATE_STATE(dst, src) memcpy(dst, src, sizeof(struct inflate_state))
18 /* Memory management for the window. Useful for allocation the aligned window. */
19 # define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size)
20 # define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr)
21 /* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */
22 # define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
23 /* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */
24 # define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
25 /* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */
26 # define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
27 /* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */
28 # define INFLATE_NEED_CHECKSUM(strm) 1
29 /* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */
30 # define INFLATE_NEED_UPDATEWINDOW(strm) 1
31 /* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */
32 # define INFLATE_MARK_HOOK(strm) do {} while (0)
33 /* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */
34 # define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
35 #endif
36
37 /*
38 * Macros shared by inflate() and inflateBack()
39 */
40
41 /* check function to use adler32() for zlib or crc32() for gzip */
42 #ifdef GUNZIP
43 # define UPDATE(check, buf, len) \
44 (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len))
45 #else
46 # define UPDATE(check, buf, len) functable.adler32(check, buf, len)
47 #endif
48
49 /* check macros for header crc */
50 #ifdef GUNZIP
51 # define CRC2(check, word) \
52 do { \
53 hbuf[0] = (unsigned char)(word); \
54 hbuf[1] = (unsigned char)((word) >> 8); \
55 check = PREFIX(crc32)(check, hbuf, 2); \
56 } while (0)
57
58 # define CRC4(check, word) \
59 do { \
60 hbuf[0] = (unsigned char)(word); \
61 hbuf[1] = (unsigned char)((word) >> 8); \
62 hbuf[2] = (unsigned char)((word) >> 16); \
63 hbuf[3] = (unsigned char)((word) >> 24); \
64 check = PREFIX(crc32)(check, hbuf, 4); \
65 } while (0)
66 #endif
67
68 /* Load registers with state in inflate() for speed */
69 #define LOAD() \
70 do { \
71 put = strm->next_out; \
72 left = strm->avail_out; \
73 next = strm->next_in; \
74 have = strm->avail_in; \
75 hold = state->hold; \
76 bits = state->bits; \
77 } while (0)
78
79 /* Restore state from registers in inflate() */
80 #define RESTORE() \
81 do { \
82 strm->next_out = put; \
83 strm->avail_out = left; \
84 strm->next_in = (z_const unsigned char *)next; \
85 strm->avail_in = have; \
86 state->hold = hold; \
87 state->bits = bits; \
88 } while (0)
89
90 /* Clear the input bit accumulator */
91 #define INITBITS() \
92 do { \
93 hold = 0; \
94 bits = 0; \
95 } while (0)
96
97 /* Ensure that there is at least n bits in the bit accumulator. If there is
98 not enough available input to do that, then return from inflate()/inflateBack(). */
99 #define NEEDBITS(n) \
100 do { \
101 while (bits < (unsigned)(n)) \
102 PULLBYTE(); \
103 } while (0)
104
105 /* Return the low n bits of the bit accumulator (n < 16) */
106 #define BITS(n) \
107 (hold & ((1U << (unsigned)(n)) - 1))
108
109 /* Remove n bits from the bit accumulator */
110 #define DROPBITS(n) \
111 do { \
112 hold >>= (n); \
113 bits -= (unsigned)(n); \
114 } while (0)
115
116 /* Remove zero to seven bits as needed to go to a byte boundary */
117 #define BYTEBITS() \
118 do { \
119 hold >>= bits & 7; \
120 bits -= bits & 7; \
121 } while (0)
122
123 #endif
124
125 /* Set mode=BAD and prepare error message */
126 #define SET_BAD(errmsg) \
127 do { \
128 state->mode = BAD; \
129 strm->msg = (char *)errmsg; \
130 } while (0)
131
132 /* Behave like chunkcopy, but avoid writing beyond of legal output. */
chunkcopy_safe(uint8_t * out,uint8_t * from,size_t len,uint8_t * safe)133 static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, uint8_t *safe) {
134 uint32_t safelen = (uint32_t)((safe - out) + 1);
135 len = MIN(len, safelen);
136 int32_t olap_src = from >= out && from < out + len;
137 int32_t olap_dst = out >= from && out < from + len;
138 size_t tocopy;
139
140 /* For all cases without overlap, memcpy is ideal */
141 if (!(olap_src || olap_dst)) {
142 memcpy(out, from, len);
143 return out + len;
144 }
145
146 /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior,
147 * we have to get a bit clever. First if the overlap is such that src falls between dst and dst+len, we can do the
148 * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest
149 * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look
150 * behind or lookahead distance. */
151 size_t non_olap_size = llabs(from - out); // llabs vs labs for compatibility with windows
152
153 memcpy(out, from, non_olap_size);
154 out += non_olap_size;
155 from += non_olap_size;
156 len -= non_olap_size;
157
158 /* So this doesn't give use a worst case scenario of function calls in a loop,
159 * we want to instead break this down into copy blocks of fixed lengths */
160 while (len) {
161 tocopy = MIN(non_olap_size, len);
162 len -= tocopy;
163
164 while (tocopy >= 32) {
165 memcpy(out, from, 32);
166 out += 32;
167 from += 32;
168 tocopy -= 32;
169 }
170
171 if (tocopy >= 16) {
172 memcpy(out, from, 16);
173 out += 16;
174 from += 16;
175 tocopy -= 16;
176 }
177
178 if (tocopy >= 8) {
179 zmemcpy_8(out, from);
180 out += 8;
181 from += 8;
182 tocopy -= 8;
183 }
184
185 if (tocopy >= 4) {
186 zmemcpy_4(out, from);
187 out += 4;
188 from += 4;
189 tocopy -= 4;
190 }
191
192 if (tocopy >= 2) {
193 zmemcpy_2(out, from);
194 out += 2;
195 from += 2;
196 tocopy -= 2;
197 }
198
199 if (tocopy) {
200 *out++ = *from++;
201 }
202 }
203
204 return out;
205 }
206