Coverage Report

Created: 2025-07-12 06:27

/src/libzip/lib/zip_buffer.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 zip_buffer.c -- bounds checked access to memory buffer
3
 Copyright (C) 2014-2024 Dieter Baron and Thomas Klausner
4
5
 This file is part of libzip, a library to manipulate ZIP archives.
6
 The authors can be contacted at <info@libzip.org>
7
8
 Redistribution and use in source and binary forms, with or without
9
 modification, are permitted provided that the following conditions
10
 are met:
11
 1. Redistributions of source code must retain the above copyright
12
 notice, this list of conditions and the following disclaimer.
13
 2. Redistributions in binary form must reproduce the above copyright
14
 notice, this list of conditions and the following disclaimer in
15
 the documentation and/or other materials provided with the
16
 distribution.
17
 3. The names of the authors may not be used to endorse or promote
18
 products derived from this software without specific prior
19
 written permission.
20
21
 THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22
 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29
 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31
 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
 */
33
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include "zipint.h"
38
39
zip_uint8_t *
40
273k
_zip_buffer_data(zip_buffer_t *buffer) {
41
273k
    return buffer->data;
42
273k
}
43
44
45
void
46
183k
_zip_buffer_free(zip_buffer_t *buffer) {
47
183k
    if (buffer == NULL) {
48
1.66k
        return;
49
1.66k
    }
50
51
181k
    if (buffer->free_data) {
52
49.5k
        free(buffer->data);
53
49.5k
    }
54
55
181k
    free(buffer);
56
181k
}
57
58
59
bool
60
66.6k
_zip_buffer_eof(zip_buffer_t *buffer) {
61
66.6k
    return buffer->ok && buffer->offset == buffer->size;
62
66.6k
}
63
64
65
zip_uint8_t *
66
2.64M
_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
67
2.64M
    zip_uint8_t *data;
68
69
2.64M
    data = _zip_buffer_peek(buffer, length);
70
71
2.64M
    if (data != NULL) {
72
2.64M
        buffer->offset += length;
73
2.64M
    }
74
75
2.64M
    return data;
76
2.64M
}
77
78
79
zip_uint16_t
80
1.59M
_zip_buffer_get_16(zip_buffer_t *buffer) {
81
1.59M
    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
82
83
1.59M
    if (data == NULL) {
84
0
        return 0;
85
0
    }
86
87
1.59M
    return (zip_uint16_t)(data[0] + (data[1] << 8));
88
1.59M
}
89
90
91
zip_uint32_t
92
659k
_zip_buffer_get_32(zip_buffer_t *buffer) {
93
659k
    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
94
95
659k
    if (data == NULL) {
96
110
        return 0;
97
110
    }
98
99
659k
    return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
100
659k
}
101
102
103
zip_uint64_t
104
23.3k
_zip_buffer_get_64(zip_buffer_t *buffer) {
105
23.3k
    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
106
107
23.3k
    if (data == NULL) {
108
185
        return 0;
109
185
    }
110
111
23.2k
    return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
112
23.3k
}
113
114
115
zip_uint8_t
116
10.4k
_zip_buffer_get_8(zip_buffer_t *buffer) {
117
10.4k
    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
118
119
10.4k
    if (data == NULL) {
120
0
        return 0;
121
0
    }
122
123
10.4k
    return data[0];
124
10.4k
}
125
126
127
zip_uint64_t
128
321k
_zip_buffer_left(zip_buffer_t *buffer) {
129
321k
    return buffer->ok ? buffer->size - buffer->offset : 0;
130
321k
}
131
132
133
zip_uint64_t
134
2.05k
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
135
2.05k
    zip_uint64_t copied;
136
137
2.05k
    if (_zip_buffer_left(buffer) < length) {
138
2.00k
        length = _zip_buffer_left(buffer);
139
2.00k
    }
140
141
2.05k
    copied = 0;
142
3.60k
    while (copied < length) {
143
1.55k
        size_t n = ZIP_MIN(length - copied, SIZE_MAX);
144
1.55k
        (void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n);
145
1.55k
        copied += n;
146
1.55k
    }
147
148
2.05k
    return copied;
149
2.05k
}
150
151
152
zip_buffer_t *
153
181k
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
154
181k
    bool free_data = (data == NULL);
155
181k
    zip_buffer_t *buffer;
156
157
#if ZIP_UINT64_MAX > SIZE_MAX
158
    if (size > SIZE_MAX) {
159
        return NULL;
160
    }
161
#endif
162
163
181k
    if (data == NULL) {
164
49.5k
        if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) {
165
0
            return NULL;
166
0
        }
167
49.5k
    }
168
169
181k
    if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
170
0
        if (free_data) {
171
0
            free(data);
172
0
        }
173
0
        return NULL;
174
0
    }
175
176
181k
    buffer->ok = true;
177
181k
    buffer->data = data;
178
181k
    buffer->size = size;
179
181k
    buffer->offset = 0;
180
181k
    buffer->free_data = free_data;
181
182
181k
    return buffer;
183
181k
}
184
185
186
zip_buffer_t *
187
119k
_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) {
188
119k
    zip_buffer_t *buffer;
189
190
119k
    if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
191
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
192
0
        return NULL;
193
0
    }
194
195
119k
    if (_zip_read(src, buffer->data, size, error) < 0) {
196
306
        _zip_buffer_free(buffer);
197
306
        return NULL;
198
306
    }
199
200
119k
    return buffer;
201
119k
}
202
203
204
zip_uint64_t
205
152k
_zip_buffer_offset(zip_buffer_t *buffer) {
206
152k
    return buffer->ok ? buffer->offset : 0;
207
152k
}
208
209
210
bool
211
320k
_zip_buffer_ok(zip_buffer_t *buffer) {
212
320k
    return buffer->ok;
213
320k
}
214
215
216
zip_uint8_t *
217
2.64M
_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
218
2.64M
    zip_uint8_t *data;
219
220
2.64M
    if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
221
1.33k
        buffer->ok = false;
222
1.33k
        return NULL;
223
1.33k
    }
224
225
2.64M
    data = buffer->data + buffer->offset;
226
2.64M
    return data;
227
2.64M
}
228
229
int
230
6.00k
_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
231
6.00k
    zip_uint8_t *dst = _zip_buffer_get(buffer, length);
232
233
6.00k
    if (dst == NULL) {
234
0
        return -1;
235
0
    }
236
237
6.00k
    (void)memcpy_s(dst, length, src, length);
238
6.00k
    return 0;
239
6.00k
}
240
241
242
int
243
34.0k
_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
244
34.0k
    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
245
246
34.0k
    if (data == NULL) {
247
0
        return -1;
248
0
    }
249
250
34.0k
    data[0] = (zip_uint8_t)(i & 0xff);
251
34.0k
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
252
253
34.0k
    return 0;
254
34.0k
}
255
256
257
int
258
15.2k
_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
259
15.2k
    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
260
261
15.2k
    if (data == NULL) {
262
0
        return -1;
263
0
    }
264
265
15.2k
    data[0] = (zip_uint8_t)(i & 0xff);
266
15.2k
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
267
15.2k
    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
268
15.2k
    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
269
270
15.2k
    return 0;
271
15.2k
}
272
273
274
int
275
2.13k
_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
276
2.13k
    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
277
278
2.13k
    if (data == NULL) {
279
0
        return -1;
280
0
    }
281
282
2.13k
    data[0] = (zip_uint8_t)(i & 0xff);
283
2.13k
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
284
2.13k
    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
285
2.13k
    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
286
2.13k
    data[4] = (zip_uint8_t)((i >> 32) & 0xff);
287
2.13k
    data[5] = (zip_uint8_t)((i >> 40) & 0xff);
288
2.13k
    data[6] = (zip_uint8_t)((i >> 48) & 0xff);
289
2.13k
    data[7] = (zip_uint8_t)((i >> 56) & 0xff);
290
291
2.13k
    return 0;
292
2.13k
}
293
294
295
int
296
1.59k
_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
297
1.59k
    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
298
299
1.59k
    if (data == NULL) {
300
0
        return -1;
301
0
    }
302
303
1.59k
    data[0] = i;
304
305
1.59k
    return 0;
306
1.59k
}
307
308
309
221k
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
310
221k
    if (offset > buffer->size) {
311
28.9k
        buffer->ok = false;
312
28.9k
        return -1;
313
28.9k
    }
314
315
192k
    buffer->ok = true;
316
192k
    buffer->offset = offset;
317
318
192k
    return 0;
319
221k
}
320
321
322
int
323
69.5k
_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
324
69.5k
    zip_uint64_t offset = buffer->offset + length;
325
326
69.5k
    if (offset < buffer->offset) {
327
0
        buffer->ok = false;
328
0
        return -1;
329
0
    }
330
69.5k
    return _zip_buffer_set_offset(buffer, offset);
331
69.5k
}
332
333
zip_uint64_t
334
9.82k
_zip_buffer_size(zip_buffer_t *buffer) {
335
9.82k
    return buffer->size;
336
9.82k
}