Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zlib-ng/inflate_p.h
Line
Count
Source
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
#include "zendian.h"
11
#include "zmemory.h"
12
#include "crc32_braid_tbl.h"
13
14
/* Architecture-specific hooks. */
15
#ifdef S390_DFLTCC_INFLATE
16
#  include "arch/s390/dfltcc_inflate.h"
17
/* DFLTCC instructions require window to be page-aligned */
18
#  define PAD_WINDOW            PAD_4096
19
#  define WINDOW_PAD_SIZE       4096
20
#  define HINT_ALIGNED_WINDOW   HINT_ALIGNED_4096
21
#else
22
#  define PAD_WINDOW            PAD_64
23
#  define WINDOW_PAD_SIZE       64
24
#  define HINT_ALIGNED_WINDOW   HINT_ALIGNED_64
25
/* Adjust the window size for the arch-specific inflate code. */
26
21.1k
#  define INFLATE_ADJUST_WINDOW_SIZE(n) (n)
27
/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */
28
10.5k
#  define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
29
/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */
30
0
#  define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
31
/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */
32
61.2k
#  define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
33
/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */
34
61.7k
#  define INFLATE_NEED_CHECKSUM(strm) 1
35
/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */
36
21.1k
#  define INFLATE_NEED_UPDATEWINDOW(strm) 1
37
/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */
38
0
#  define INFLATE_MARK_HOOK(strm) do {} while (0)
39
/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */
40
0
#  define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
41
/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */
42
10.1k
#  define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
43
/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */
44
0
#  define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
45
#endif
46
47
/*
48
 *   Macros shared by inflate() and inflateBack()
49
 */
50
51
/* check macros for header crc */
52
#ifdef GUNZIP
53
0
#  define CRC_DO1_B(c, b)    c = crc_table[(c ^ (b)) & 0xff] ^ (c >> 8)
54
55
#  define CRC2(check, word) \
56
0
    do { \
57
0
        uint32_t crc = ~(uint32_t)(check); \
58
0
        CRC_DO1_B(crc, (word)     ); \
59
0
        CRC_DO1_B(crc, (word) >> 8); \
60
0
        (check) = ~crc; \
61
0
    } while (0)
62
63
#  define CRC4(check, word) \
64
0
    do { \
65
0
        uint32_t crc = ~(uint32_t)(check); \
66
0
        CRC_DO1_B(crc, (word)      ); \
67
0
        CRC_DO1_B(crc, (word) >>  8); \
68
0
        CRC_DO1_B(crc, (word) >> 16); \
69
0
        CRC_DO1_B(crc, (word) >> 24); \
70
0
        (check) = ~crc; \
71
0
    } while (0)
72
#endif
73
74
/* Compiler optimization for bit accumulator on x86 architectures */
75
#ifdef ARCH_X86
76
typedef uint8_t bits_t;
77
#else
78
typedef unsigned bits_t;
79
#endif
80
81
/* Load registers with state in inflate() for speed */
82
#define LOAD() \
83
67.2k
    do { \
84
67.2k
        put = strm->next_out; \
85
67.2k
        left = strm->avail_out; \
86
67.2k
        next = strm->next_in; \
87
67.2k
        have = strm->avail_in; \
88
67.2k
        hold = state->hold; \
89
67.2k
        bits = (bits_t)state->bits; \
90
67.2k
    } while (0)
91
92
/* Restore state from registers in inflate() */
93
#define RESTORE() \
94
67.2k
    do { \
95
67.2k
        strm->next_out = put; \
96
67.2k
        strm->avail_out = left; \
97
67.2k
        strm->next_in = (z_const unsigned char *)next; \
98
67.2k
        strm->avail_in = have; \
99
67.2k
        state->hold = hold; \
100
67.2k
        state->bits = bits; \
101
67.2k
    } while (0)
102
103
/* Refill to have at least 56 bits in the bit accumulator */
104
4.19M
#define REFILL() do { \
105
4.19M
        hold |= load_64_bits(in, bits); \
106
4.19M
        in += (63 ^ bits) >> 3; \
107
4.19M
        bits |= 56; \
108
4.19M
    } while (0)
109
110
/* Clear the input bit accumulator */
111
#define INITBITS() \
112
38.1k
    do { \
113
38.1k
        hold = 0; \
114
38.1k
        bits = 0; \
115
38.1k
    } while (0)
116
117
/* Ensure that there is at least n bits in the bit accumulator.  If there is
118
   not enough available input to do that, then return from inflate()/inflateBack(). */
119
#define NEEDBITS(n) \
120
899k
    do { \
121
899k
        unsigned u = (unsigned)(n); \
122
1.45M
        while (bits < (bits_t)u) \
123
899k
            PULLBYTE(); \
124
899k
    } while (0)
125
126
/* Return the low n bits of the bit accumulator (n < 16) */
127
#define BITS(n) \
128
2.98M
    (hold & ((1U << (unsigned)(n)) - 1))
129
130
/* Remove n bits from the bit accumulator */
131
#define DROPBITS(n) \
132
14.4M
    do { \
133
14.4M
        unsigned u = (unsigned)(n); \
134
14.4M
        hold >>= u; \
135
14.4M
        bits -= (bits_t)u; \
136
14.4M
    } while (0)
137
138
/* Remove zero to seven bits as needed to go to a byte boundary */
139
#define BYTEBITS() \
140
17.4k
    do { \
141
17.4k
        hold >>= bits & 7; \
142
17.4k
        bits -= bits & 7; \
143
17.4k
    } while (0)
144
145
/* Set mode=BAD and prepare error message */
146
#define SET_BAD(errmsg) \
147
0
    do { \
148
0
        state->mode = BAD; \
149
0
        strm->msg = (char *)errmsg; \
150
0
    } while (0)
151
152
/* Huffman code table entry format for length/distance codes (op & 16 set):
153
 *   bits = code_bits + extra_bits (combined for single-shift decode)
154
 *   op   = 16 | code_bits
155
 *   val  = base value
156
 *
157
 * For literals (op == 0): bits = code_bits, val = literal byte
158
 */
159
160
/* Extract code size from a Huffman table entry */
161
#define CODE_BITS(here) \
162
50.4k
    ((unsigned)((here.op & 16) ? (here.op & 15) : here.bits))
163
164
/* Extract extra bits count from a length/distance code entry */
165
#define CODE_EXTRA(here) \
166
0
    ((unsigned)((here.op & 16) ? (here.bits - (here.op & 15)) : 0))
167
168
/* Extract extra bits value from saved bit accumulator */
169
#define EXTRA_BITS(old, here, op) \
170
1.25M
    ((old & (((uint64_t)1 << here.bits) - 1)) >> (op & MAX_BITS))
171
172
/* Build combined op field: preserves extra if not len/dist, else combines with code_bits */
173
#define COMBINE_OP(extra, code_bits) \
174
141k
    ((unsigned char)((extra) & 16 ? (code_bits) | 16 : (extra)))
175
176
/* Build combined bits field: code_bits + extra_bits from extra's low nibble */
177
#define COMBINE_BITS(code_bits, extra) \
178
141k
    ((unsigned char)((code_bits) + ((extra) & 15)))
179
180
/* Trace macros for debugging */
181
#define TRACE_LITERAL(val) \
182
    Tracevv((stderr, val >= 0x20 && val < 0x7f ? \
183
            "inflate:         literal '%c'\n" : \
184
            "inflate:         literal 0x%02x\n", val))
185
186
#define TRACE_LENGTH(len) \
187
    Tracevv((stderr, "inflate:         length %u\n", len))
188
189
#define TRACE_DISTANCE(dist) \
190
    Tracevv((stderr, "inflate:         distance %u\n", dist))
191
192
#define TRACE_END_OF_BLOCK() \
193
    Tracevv((stderr, "inflate:         end of block\n"))
194
195
/* inflate_fast() executes at most two 8-byte refill reads per iteration: the
196
   first at the input position validated by the loop bound (advancing at most
197
   7 bytes), the second therefore ending at most 15 bytes past that position.
198
   The refill before the loop reads at the entry position and advances exactly
199
   7 bytes (entry guarantees bits < 8), so the first iteration stays within
200
   the same bound. */
201
220k
#define INFLATE_FAST_MIN_HAVE 15
202
81.3k
#define INFLATE_FAST_MIN_LEFT 260  /* max output per token (258) + 2 */
203
75.5k
#define INFLATE_FAST_MIN_SAFE 3    /* max unchecked literal writes per iteration */
204
205
/* Load 64 bits from IN and place the bytes at offset BITS in the result. */
206
4.19M
static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) {
207
4.19M
    uint64_t chunk = zng_memread_8(in);
208
4.19M
    return Z_U64_FROM_LE(chunk) << bits;
209
4.19M
}
Unexecuted instantiation: inflate.c:load_64_bits
Unexecuted instantiation: inftrees.c:load_64_bits
Unexecuted instantiation: chunkset_sse2.c:load_64_bits
Unexecuted instantiation: chunkset_ssse3.c:load_64_bits
chunkset_avx2.c:load_64_bits
Line
Count
Source
206
4.19M
static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) {
207
4.19M
    uint64_t chunk = zng_memread_8(in);
208
4.19M
    return Z_U64_FROM_LE(chunk) << bits;
209
4.19M
}
Unexecuted instantiation: chunkset_avx512.c:load_64_bits
210
211
/* Behave like chunkcopy, but avoid writing beyond of legal output. */
212
43.0k
static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, uint8_t *safe) {
213
43.0k
    size_t safelen = safe - out;
214
43.0k
    len = MIN(len, safelen);
215
43.0k
    int32_t olap_src = from >= out && from < out + len;
216
43.0k
    int32_t olap_dst = out >= from && out < from + len;
217
43.0k
    size_t tocopy;
218
219
    /* For all cases without overlap, memcpy is ideal */
220
43.0k
    if (!(olap_src || olap_dst)) {
221
27.3k
        memcpy(out, from, len);
222
27.3k
        return out + len;
223
27.3k
    }
224
225
    /* Complete overlap: Source == destination */
226
15.7k
    if (out == from) {
227
0
        return out + len;
228
0
    }
229
230
    /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior,
231
     * 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
232
     * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest
233
     * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look
234
     * behind or lookahead distance. */
235
15.7k
    size_t non_olap_size = (size_t)ABS(from - out);
236
237
    /* So this doesn't give use a worst case scenario of function calls in a loop,
238
     * we want to instead break this down into copy blocks of fixed lengths
239
     *
240
     * TODO: The memcpy calls aren't inlined on architectures with strict memory alignment
241
     */
242
614k
    while (len) {
243
598k
        tocopy = MIN(non_olap_size, len);
244
598k
        len -= tocopy;
245
246
599k
        while (tocopy >= 16) {
247
445
            memcpy(out, from, 16);
248
445
            out += 16;
249
445
            from += 16;
250
445
            tocopy -= 16;
251
445
        }
252
253
598k
        if (tocopy >= 8) {
254
372
            memcpy(out, from, 8);
255
372
            out += 8;
256
372
            from += 8;
257
372
            tocopy -= 8;
258
372
        }
259
260
598k
        if (tocopy >= 4) {
261
726
            memcpy(out, from, 4);
262
726
            out += 4;
263
726
            from += 4;
264
726
            tocopy -= 4;
265
726
        }
266
267
1.20M
        while (tocopy--) {
268
601k
            *out++ = *from++;
269
601k
        }
270
598k
    }
271
272
15.7k
    return out;
273
15.7k
}
Unexecuted instantiation: inflate.c:chunkcopy_safe
Unexecuted instantiation: inftrees.c:chunkcopy_safe
Unexecuted instantiation: chunkset_sse2.c:chunkcopy_safe
Unexecuted instantiation: chunkset_ssse3.c:chunkcopy_safe
chunkset_avx2.c:chunkcopy_safe
Line
Count
Source
212
43.0k
static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, uint8_t *safe) {
213
43.0k
    size_t safelen = safe - out;
214
43.0k
    len = MIN(len, safelen);
215
43.0k
    int32_t olap_src = from >= out && from < out + len;
216
43.0k
    int32_t olap_dst = out >= from && out < from + len;
217
43.0k
    size_t tocopy;
218
219
    /* For all cases without overlap, memcpy is ideal */
220
43.0k
    if (!(olap_src || olap_dst)) {
221
27.3k
        memcpy(out, from, len);
222
27.3k
        return out + len;
223
27.3k
    }
224
225
    /* Complete overlap: Source == destination */
226
15.7k
    if (out == from) {
227
0
        return out + len;
228
0
    }
229
230
    /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior,
231
     * 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
232
     * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest
233
     * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look
234
     * behind or lookahead distance. */
235
15.7k
    size_t non_olap_size = (size_t)ABS(from - out);
236
237
    /* So this doesn't give use a worst case scenario of function calls in a loop,
238
     * we want to instead break this down into copy blocks of fixed lengths
239
     *
240
     * TODO: The memcpy calls aren't inlined on architectures with strict memory alignment
241
     */
242
614k
    while (len) {
243
598k
        tocopy = MIN(non_olap_size, len);
244
598k
        len -= tocopy;
245
246
599k
        while (tocopy >= 16) {
247
445
            memcpy(out, from, 16);
248
445
            out += 16;
249
445
            from += 16;
250
445
            tocopy -= 16;
251
445
        }
252
253
598k
        if (tocopy >= 8) {
254
372
            memcpy(out, from, 8);
255
372
            out += 8;
256
372
            from += 8;
257
372
            tocopy -= 8;
258
372
        }
259
260
598k
        if (tocopy >= 4) {
261
726
            memcpy(out, from, 4);
262
726
            out += 4;
263
726
            from += 4;
264
726
            tocopy -= 4;
265
726
        }
266
267
1.20M
        while (tocopy--) {
268
601k
            *out++ = *from++;
269
601k
        }
270
598k
    }
271
272
15.7k
    return out;
273
15.7k
}
Unexecuted instantiation: chunkset_avx512.c:chunkcopy_safe
274
275
#endif