Coverage Report

Created: 2025-07-23 08:18

/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
0
_zip_buffer_data(zip_buffer_t *buffer) {
41
0
    return buffer->data;
42
0
}
43
44
45
void
46
0
_zip_buffer_free(zip_buffer_t *buffer) {
47
0
    if (buffer == NULL) {
48
0
        return;
49
0
    }
50
51
0
    if (buffer->free_data) {
52
0
        free(buffer->data);
53
0
    }
54
55
0
    free(buffer);
56
0
}
57
58
59
bool
60
0
_zip_buffer_eof(zip_buffer_t *buffer) {
61
0
    return buffer->ok && buffer->offset == buffer->size;
62
0
}
63
64
65
zip_uint8_t *
66
0
_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
67
0
    zip_uint8_t *data;
68
69
0
    data = _zip_buffer_peek(buffer, length);
70
71
0
    if (data != NULL) {
72
0
        buffer->offset += length;
73
0
    }
74
75
0
    return data;
76
0
}
77
78
79
zip_uint16_t
80
0
_zip_buffer_get_16(zip_buffer_t *buffer) {
81
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
82
83
0
    if (data == NULL) {
84
0
        return 0;
85
0
    }
86
87
0
    return (zip_uint16_t)(data[0] + (data[1] << 8));
88
0
}
89
90
91
zip_uint32_t
92
0
_zip_buffer_get_32(zip_buffer_t *buffer) {
93
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
94
95
0
    if (data == NULL) {
96
0
        return 0;
97
0
    }
98
99
0
    return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
100
0
}
101
102
103
zip_uint64_t
104
0
_zip_buffer_get_64(zip_buffer_t *buffer) {
105
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
106
107
0
    if (data == NULL) {
108
0
        return 0;
109
0
    }
110
111
0
    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
0
}
113
114
115
zip_uint8_t
116
0
_zip_buffer_get_8(zip_buffer_t *buffer) {
117
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
118
119
0
    if (data == NULL) {
120
0
        return 0;
121
0
    }
122
123
0
    return data[0];
124
0
}
125
126
127
zip_uint64_t
128
0
_zip_buffer_left(zip_buffer_t *buffer) {
129
0
    return buffer->ok ? buffer->size - buffer->offset : 0;
130
0
}
131
132
133
zip_uint64_t
134
0
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
135
0
    zip_uint64_t copied;
136
137
0
    if (_zip_buffer_left(buffer) < length) {
138
0
        length = _zip_buffer_left(buffer);
139
0
    }
140
141
0
    copied = 0;
142
0
    while (copied < length) {
143
0
        size_t n = ZIP_MIN(length - copied, SIZE_MAX);
144
0
        (void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n);
145
0
        copied += n;
146
0
    }
147
148
0
    return copied;
149
0
}
150
151
152
zip_buffer_t *
153
0
_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
154
0
    bool free_data = (data == NULL);
155
0
    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
0
    if (data == NULL) {
164
0
        if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) {
165
0
            return NULL;
166
0
        }
167
0
    }
168
169
0
    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
0
    buffer->ok = true;
177
0
    buffer->data = data;
178
0
    buffer->size = size;
179
0
    buffer->offset = 0;
180
0
    buffer->free_data = free_data;
181
182
0
    return buffer;
183
0
}
184
185
186
zip_buffer_t *
187
0
_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) {
188
0
    zip_buffer_t *buffer;
189
190
0
    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
0
    if (_zip_read(src, buffer->data, size, error) < 0) {
196
0
        _zip_buffer_free(buffer);
197
0
        return NULL;
198
0
    }
199
200
0
    return buffer;
201
0
}
202
203
204
zip_uint64_t
205
0
_zip_buffer_offset(zip_buffer_t *buffer) {
206
0
    return buffer->ok ? buffer->offset : 0;
207
0
}
208
209
210
bool
211
0
_zip_buffer_ok(zip_buffer_t *buffer) {
212
0
    return buffer->ok;
213
0
}
214
215
216
zip_uint8_t *
217
0
_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
218
0
    zip_uint8_t *data;
219
220
0
    if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
221
0
        buffer->ok = false;
222
0
        return NULL;
223
0
    }
224
225
0
    data = buffer->data + buffer->offset;
226
0
    return data;
227
0
}
228
229
int
230
0
_zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
231
0
    zip_uint8_t *dst = _zip_buffer_get(buffer, length);
232
233
0
    if (dst == NULL) {
234
0
        return -1;
235
0
    }
236
237
0
    (void)memcpy_s(dst, length, src, length);
238
0
    return 0;
239
0
}
240
241
242
int
243
0
_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
244
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 2);
245
246
0
    if (data == NULL) {
247
0
        return -1;
248
0
    }
249
250
0
    data[0] = (zip_uint8_t)(i & 0xff);
251
0
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
252
253
0
    return 0;
254
0
}
255
256
257
int
258
0
_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
259
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 4);
260
261
0
    if (data == NULL) {
262
0
        return -1;
263
0
    }
264
265
0
    data[0] = (zip_uint8_t)(i & 0xff);
266
0
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
267
0
    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
268
0
    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
269
270
0
    return 0;
271
0
}
272
273
274
int
275
0
_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
276
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 8);
277
278
0
    if (data == NULL) {
279
0
        return -1;
280
0
    }
281
282
0
    data[0] = (zip_uint8_t)(i & 0xff);
283
0
    data[1] = (zip_uint8_t)((i >> 8) & 0xff);
284
0
    data[2] = (zip_uint8_t)((i >> 16) & 0xff);
285
0
    data[3] = (zip_uint8_t)((i >> 24) & 0xff);
286
0
    data[4] = (zip_uint8_t)((i >> 32) & 0xff);
287
0
    data[5] = (zip_uint8_t)((i >> 40) & 0xff);
288
0
    data[6] = (zip_uint8_t)((i >> 48) & 0xff);
289
0
    data[7] = (zip_uint8_t)((i >> 56) & 0xff);
290
291
0
    return 0;
292
0
}
293
294
295
int
296
0
_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
297
0
    zip_uint8_t *data = _zip_buffer_get(buffer, 1);
298
299
0
    if (data == NULL) {
300
0
        return -1;
301
0
    }
302
303
0
    data[0] = i;
304
305
0
    return 0;
306
0
}
307
308
309
0
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
310
0
    if (offset > buffer->size) {
311
0
        buffer->ok = false;
312
0
        return -1;
313
0
    }
314
315
0
    buffer->ok = true;
316
0
    buffer->offset = offset;
317
318
0
    return 0;
319
0
}
320
321
322
int
323
0
_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
324
0
    zip_uint64_t offset = buffer->offset + length;
325
326
0
    if (offset < buffer->offset) {
327
0
        buffer->ok = false;
328
0
        return -1;
329
0
    }
330
0
    return _zip_buffer_set_offset(buffer, offset);
331
0
}
332
333
zip_uint64_t
334
0
_zip_buffer_size(zip_buffer_t *buffer) {
335
0
    return buffer->size;
336
0
}