Coverage Report

Created: 2025-04-11 06:10

/src/minizip-ng/mz_strm.c
Line
Count
Source (jump to first uncovered line)
1
/* mz_strm.c -- Stream interface
2
   part of the minizip-ng project
3
4
   Copyright (C) Nathan Moinvaziri
5
     https://github.com/zlib-ng/minizip-ng
6
7
   This program is distributed under the terms of the same license as zlib.
8
   See the accompanying LICENSE file for the full text of the license.
9
*/
10
11
#include "mz.h"
12
#include "mz_strm.h"
13
14
/***************************************************************************/
15
16
21.2M
#define MZ_STREAM_FIND_SIZE (1024)
17
18
/***************************************************************************/
19
20
47.6k
int32_t mz_stream_open(void *stream, const char *path, int32_t mode) {
21
47.6k
    mz_stream *strm = (mz_stream *)stream;
22
47.6k
    if (!strm || !strm->vtbl || !strm->vtbl->open)
23
0
        return MZ_STREAM_ERROR;
24
47.6k
    return strm->vtbl->open(strm, path, mode);
25
47.6k
}
26
27
24.8M
int32_t mz_stream_is_open(void *stream) {
28
24.8M
    mz_stream *strm = (mz_stream *)stream;
29
24.8M
    if (!strm || !strm->vtbl || !strm->vtbl->is_open)
30
0
        return MZ_STREAM_ERROR;
31
24.8M
    return strm->vtbl->is_open(strm);
32
24.8M
}
33
34
12.6M
int32_t mz_stream_read(void *stream, void *buf, int32_t size) {
35
12.6M
    mz_stream *strm = (mz_stream *)stream;
36
12.6M
    if (!strm || !strm->vtbl || !strm->vtbl->read)
37
0
        return MZ_PARAM_ERROR;
38
12.6M
    if (mz_stream_is_open(stream) != MZ_OK)
39
0
        return MZ_STREAM_ERROR;
40
12.6M
    return strm->vtbl->read(strm, buf, size);
41
12.6M
}
42
43
11.6M
static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len) {
44
11.6M
    uint8_t buf[8];
45
11.6M
    int32_t n = 0;
46
11.6M
    int32_t i = 0;
47
48
11.6M
    *value = 0;
49
11.6M
    if (mz_stream_read(stream, buf, len) == len) {
50
44.5M
        for (n = 0; n < len; n += 1, i += 8)
51
32.9M
            *value += ((uint64_t)buf[n]) << i;
52
11.6M
    } else if (mz_stream_error(stream))
53
0
        return MZ_STREAM_ERROR;
54
34.3k
    else
55
34.3k
        return MZ_END_OF_STREAM;
56
57
11.6M
    return MZ_OK;
58
11.6M
}
59
60
240k
int32_t mz_stream_read_uint8(void *stream, uint8_t *value) {
61
240k
    int32_t err = MZ_OK;
62
240k
    uint64_t value64 = 0;
63
64
240k
    *value = 0;
65
240k
    err = mz_stream_read_value(stream, &value64, sizeof(uint8_t));
66
240k
    if (err == MZ_OK)
67
239k
        *value = (uint8_t)value64;
68
240k
    return err;
69
240k
}
70
71
6.79M
int32_t mz_stream_read_uint16(void *stream, uint16_t *value) {
72
6.79M
    int32_t err = MZ_OK;
73
6.79M
    uint64_t value64 = 0;
74
75
6.79M
    *value = 0;
76
6.79M
    err = mz_stream_read_value(stream, &value64, sizeof(uint16_t));
77
6.79M
    if (err == MZ_OK)
78
6.76M
        *value = (uint16_t)value64;
79
6.79M
    return err;
80
6.79M
}
81
82
4.45M
int32_t mz_stream_read_uint32(void *stream, uint32_t *value) {
83
4.45M
    int32_t err = MZ_OK;
84
4.45M
    uint64_t value64 = 0;
85
86
4.45M
    *value = 0;
87
4.45M
    err = mz_stream_read_value(stream, &value64, sizeof(uint32_t));
88
4.45M
    if (err == MZ_OK)
89
4.44M
        *value = (uint32_t)value64;
90
4.45M
    return err;
91
4.45M
}
92
93
88.3k
int32_t mz_stream_read_int64(void *stream, int64_t *value) {
94
88.3k
    return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t));
95
88.3k
}
96
97
80.6k
int32_t mz_stream_read_uint64(void *stream, uint64_t *value) {
98
80.6k
    return mz_stream_read_value(stream, value, sizeof(uint64_t));
99
80.6k
}
100
101
7.13M
int32_t mz_stream_write(void *stream, const void *buf, int32_t size) {
102
7.13M
    mz_stream *strm = (mz_stream *)stream;
103
7.13M
    if (size == 0)
104
193k
        return size;
105
6.94M
    if (!strm || !strm->vtbl || !strm->vtbl->write)
106
0
        return MZ_PARAM_ERROR;
107
6.94M
    if (mz_stream_is_open(stream) != MZ_OK)
108
0
        return MZ_STREAM_ERROR;
109
6.94M
    return strm->vtbl->write(strm, buf, size);
110
6.94M
}
111
112
6.15M
static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len) {
113
6.15M
    uint8_t buf[8];
114
6.15M
    int32_t n = 0;
115
116
18.6M
    for (n = 0; n < len; n += 1) {
117
12.4M
        buf[n] = (uint8_t)(value & 0xff);
118
12.4M
        value >>= 8;
119
12.4M
    }
120
121
6.15M
    if (value != 0) {
122
        /* Data overflow - hack for ZIP64 (X Roche) */
123
0
        for (n = 0; n < len; n += 1)
124
0
            buf[n] = 0xff;
125
0
    }
126
127
6.15M
    if (mz_stream_write(stream, buf, len) != len)
128
0
        return MZ_STREAM_ERROR;
129
130
6.15M
    return MZ_OK;
131
6.15M
}
132
133
2.79M
int32_t mz_stream_write_uint8(void *stream, uint8_t value) {
134
2.79M
    return mz_stream_write_value(stream, value, sizeof(uint8_t));
135
2.79M
}
136
137
1.93M
int32_t mz_stream_write_uint16(void *stream, uint16_t value) {
138
1.93M
    return mz_stream_write_value(stream, value, sizeof(uint16_t));
139
1.93M
}
140
141
1.39M
int32_t mz_stream_write_uint32(void *stream, uint32_t value) {
142
1.39M
    return mz_stream_write_value(stream, value, sizeof(uint32_t));
143
1.39M
}
144
145
23.2k
int32_t mz_stream_write_int64(void *stream, int64_t value) {
146
23.2k
    return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t));
147
23.2k
}
148
149
4.13k
int32_t mz_stream_write_uint64(void *stream, uint64_t value) {
150
4.13k
    return mz_stream_write_value(stream, value, sizeof(uint64_t));
151
4.13k
}
152
153
666k
int32_t mz_stream_copy(void *target, void *source, int32_t len) {
154
666k
    return mz_stream_copy_stream(target, NULL, source, NULL, len);
155
666k
}
156
157
0
int32_t mz_stream_copy_to_end(void *target, void *source) {
158
0
    return mz_stream_copy_stream_to_end(target, NULL, source, NULL);
159
0
}
160
161
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb,
162
666k
                              int32_t len) {
163
666k
    uint8_t buf[16384];
164
666k
    int32_t bytes_to_copy = 0;
165
666k
    int32_t read = 0;
166
666k
    int32_t written = 0;
167
168
666k
    if (!write_cb)
169
666k
        write_cb = mz_stream_write;
170
666k
    if (!read_cb)
171
666k
        read_cb = mz_stream_read;
172
173
1.28M
    while (len > 0) {
174
621k
        bytes_to_copy = len;
175
621k
        if (bytes_to_copy > (int32_t)sizeof(buf))
176
4.75k
            bytes_to_copy = sizeof(buf);
177
621k
        read = read_cb(source, buf, bytes_to_copy);
178
621k
        if (read <= 0)
179
6.77k
            return MZ_STREAM_ERROR;
180
614k
        written = write_cb(target, buf, read);
181
614k
        if (written != read)
182
0
            return MZ_STREAM_ERROR;
183
614k
        len -= read;
184
614k
    }
185
186
659k
    return MZ_OK;
187
666k
}
188
189
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source,
190
0
                                     mz_stream_read_cb read_cb) {
191
0
    uint8_t buf[16384];
192
0
    int32_t read = 0;
193
0
    int32_t written = 0;
194
195
0
    if (!write_cb)
196
0
        write_cb = mz_stream_write;
197
0
    if (!read_cb)
198
0
        read_cb = mz_stream_read;
199
200
0
    read = read_cb(source, buf, sizeof(buf));
201
0
    while (read > 0) {
202
0
        written = write_cb(target, buf, read);
203
0
        if (written != read)
204
0
            return MZ_STREAM_ERROR;
205
0
        read = read_cb(source, buf, sizeof(buf));
206
0
    }
207
208
0
    if (read < 0)
209
0
        return MZ_STREAM_ERROR;
210
211
0
    return MZ_OK;
212
0
}
213
214
2.98M
int64_t mz_stream_tell(void *stream) {
215
2.98M
    mz_stream *strm = (mz_stream *)stream;
216
2.98M
    if (!strm || !strm->vtbl || !strm->vtbl->tell)
217
0
        return MZ_PARAM_ERROR;
218
2.98M
    if (mz_stream_is_open(stream) != MZ_OK)
219
0
        return MZ_STREAM_ERROR;
220
2.98M
    return strm->vtbl->tell(strm);
221
2.98M
}
222
223
2.13M
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin) {
224
2.13M
    mz_stream *strm = (mz_stream *)stream;
225
2.13M
    if (!strm || !strm->vtbl || !strm->vtbl->seek)
226
0
        return MZ_PARAM_ERROR;
227
2.13M
    if (mz_stream_is_open(stream) != MZ_OK)
228
0
        return MZ_STREAM_ERROR;
229
2.13M
    if (origin == MZ_SEEK_SET && offset < 0)
230
555
        return MZ_SEEK_ERROR;
231
2.13M
    return strm->vtbl->seek(strm, offset, origin);
232
2.13M
}
233
234
209k
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
235
209k
    uint8_t buf[MZ_STREAM_FIND_SIZE];
236
209k
    int32_t buf_pos = 0;
237
209k
    int32_t read_size = sizeof(buf);
238
209k
    int32_t read = 0;
239
209k
    int64_t read_pos = 0;
240
209k
    int64_t start_pos = 0;
241
209k
    int64_t disk_pos = 0;
242
209k
    int32_t i = 0;
243
209k
    uint8_t first = 1;
244
209k
    int32_t err = MZ_OK;
245
246
209k
    if (!stream || !find || !position)
247
0
        return MZ_PARAM_ERROR;
248
209k
    if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
249
0
        return MZ_PARAM_ERROR;
250
251
209k
    *position = -1;
252
253
209k
    start_pos = mz_stream_tell(stream);
254
255
222k
    while (read_pos < max_seek) {
256
222k
        if (read_size > (int32_t)(max_seek - read_pos - buf_pos) &&
257
222k
            (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf)) {
258
0
            read_size = (int32_t)(max_seek - read_pos - buf_pos);
259
0
        }
260
261
222k
        read = mz_stream_read(stream, buf + buf_pos, read_size);
262
222k
        if ((read <= 0) || (read + buf_pos < find_size))
263
1.08k
            break;
264
265
14.0M
        for (i = 0; i <= read + buf_pos - find_size; i += 1) {
266
14.0M
            if (memcmp(&buf[i], find, find_size) != 0)
267
13.8M
                continue;
268
269
208k
            disk_pos = mz_stream_tell(stream);
270
271
            /* Seek to position on disk where the data was found */
272
208k
            err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET);
273
208k
            if (err != MZ_OK)
274
0
                return MZ_EXIST_ERROR;
275
276
208k
            *position = start_pos + read_pos + i;
277
208k
            return MZ_OK;
278
208k
        }
279
280
12.9k
        if (first) {
281
1.29k
            read -= find_size;
282
1.29k
            read_size -= find_size;
283
1.29k
            buf_pos = find_size;
284
1.29k
            first = 0;
285
1.29k
        }
286
287
12.9k
        memmove(buf, buf + read, find_size);
288
12.9k
        read_pos += read;
289
12.9k
    }
290
291
1.08k
    return MZ_EXIST_ERROR;
292
209k
}
293
294
42.1k
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
295
42.1k
    uint8_t buf[MZ_STREAM_FIND_SIZE];
296
42.1k
    int32_t buf_pos = 0;
297
42.1k
    int32_t read_size = MZ_STREAM_FIND_SIZE;
298
42.1k
    int64_t read_pos = 0;
299
42.1k
    int32_t read = 0;
300
42.1k
    int64_t start_pos = 0;
301
42.1k
    int64_t disk_pos = 0;
302
42.1k
    uint8_t first = 1;
303
42.1k
    int32_t i = 0;
304
42.1k
    int32_t err = MZ_OK;
305
306
42.1k
    if (!stream || !find || !position)
307
0
        return MZ_PARAM_ERROR;
308
42.1k
    if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
309
0
        return MZ_PARAM_ERROR;
310
311
42.1k
    *position = -1;
312
313
42.1k
    start_pos = mz_stream_tell(stream);
314
315
105k
    while (read_pos < max_seek) {
316
83.4k
        if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf))
317
63.4k
            read_size = (int32_t)(max_seek - read_pos);
318
319
83.4k
        if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK)
320
0
            break;
321
83.4k
        read = mz_stream_read(stream, buf, read_size);
322
83.4k
        if ((read <= 0) || (read + buf_pos < find_size))
323
3
            break;
324
83.4k
        if (read + buf_pos < MZ_STREAM_FIND_SIZE)
325
63.5k
            memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read);
326
327
21.1M
        for (i = find_size; i <= (read + buf_pos); i += 1) {
328
21.0M
            if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0)
329
21.0M
                continue;
330
331
20.5k
            disk_pos = mz_stream_tell(stream);
332
333
            /* Seek to position on disk where the data was found */
334
20.5k
            err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET);
335
20.5k
            if (err != MZ_OK)
336
0
                return MZ_EXIST_ERROR;
337
338
20.5k
            *position = start_pos - (read_pos - buf_pos + i);
339
20.5k
            return MZ_OK;
340
20.5k
        }
341
342
62.9k
        if (first) {
343
22.1k
            read -= find_size;
344
22.1k
            read_size -= find_size;
345
22.1k
            buf_pos = find_size;
346
22.1k
            first = 0;
347
22.1k
        }
348
349
62.9k
        if (read == 0)
350
32
            break;
351
352
62.9k
        memmove(buf + read_size, buf, find_size);
353
62.9k
        read_pos += read;
354
62.9k
    }
355
356
21.6k
    return MZ_EXIST_ERROR;
357
42.1k
}
358
359
28.7k
int32_t mz_stream_close(void *stream) {
360
28.7k
    mz_stream *strm = (mz_stream *)stream;
361
28.7k
    if (!strm || !strm->vtbl || !strm->vtbl->close)
362
0
        return MZ_PARAM_ERROR;
363
28.7k
    if (mz_stream_is_open(stream) != MZ_OK)
364
3.30k
        return MZ_STREAM_ERROR;
365
25.4k
    return strm->vtbl->close(strm);
366
28.7k
}
367
368
34.3k
int32_t mz_stream_error(void *stream) {
369
34.3k
    mz_stream *strm = (mz_stream *)stream;
370
34.3k
    if (!strm || !strm->vtbl || !strm->vtbl->error)
371
0
        return MZ_PARAM_ERROR;
372
34.3k
    return strm->vtbl->error(strm);
373
34.3k
}
374
375
47.8k
int32_t mz_stream_set_base(void *stream, void *base) {
376
47.8k
    mz_stream *strm = (mz_stream *)stream;
377
47.8k
    strm->base = (mz_stream *)base;
378
47.8k
    return MZ_OK;
379
47.8k
}
380
381
0
void *mz_stream_get_interface(void *stream) {
382
0
    mz_stream *strm = (mz_stream *)stream;
383
0
    if (!strm || !strm->vtbl)
384
0
        return NULL;
385
0
    return (void *)strm->vtbl;
386
0
}
387
388
277k
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
389
277k
    mz_stream *strm = (mz_stream *)stream;
390
277k
    if (!strm || !strm->vtbl || !strm->vtbl->get_prop_int64)
391
206k
        return MZ_PARAM_ERROR;
392
71.0k
    return strm->vtbl->get_prop_int64(stream, prop, value);
393
277k
}
394
395
547k
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value) {
396
547k
    mz_stream *strm = (mz_stream *)stream;
397
547k
    if (!strm || !strm->vtbl || !strm->vtbl->set_prop_int64)
398
500k
        return MZ_PARAM_ERROR;
399
47.1k
    return strm->vtbl->set_prop_int64(stream, prop, value);
400
547k
}
401
402
0
void *mz_stream_create(mz_stream_vtbl *vtbl) {
403
0
    if (!vtbl || !vtbl->create)
404
0
        return NULL;
405
0
    return vtbl->create();
406
0
}
407
408
52.5k
void mz_stream_delete(void **stream) {
409
52.5k
    mz_stream *strm = NULL;
410
52.5k
    if (!stream)
411
0
        return;
412
52.5k
    strm = (mz_stream *)*stream;
413
52.5k
    if (strm && strm->vtbl && strm->vtbl->destroy)
414
52.5k
        strm->vtbl->destroy(stream);
415
52.5k
    *stream = NULL;
416
52.5k
}
417
418
/***************************************************************************/
419
420
typedef struct mz_stream_raw_s {
421
    mz_stream stream;
422
    int64_t total_in;
423
    int64_t total_out;
424
    int64_t max_total_in;
425
} mz_stream_raw;
426
427
/***************************************************************************/
428
429
31.6k
int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode) {
430
31.6k
    MZ_UNUSED(stream);
431
31.6k
    MZ_UNUSED(path);
432
31.6k
    MZ_UNUSED(mode);
433
434
31.6k
    return MZ_OK;
435
31.6k
}
436
437
69.2k
int32_t mz_stream_raw_is_open(void *stream) {
438
69.2k
    mz_stream_raw *raw = (mz_stream_raw *)stream;
439
69.2k
    return mz_stream_is_open(raw->stream.base);
440
69.2k
}
441
442
29.5k
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size) {
443
29.5k
    mz_stream_raw *raw = (mz_stream_raw *)stream;
444
29.5k
    int32_t bytes_to_read = size;
445
29.5k
    int32_t read = 0;
446
447
29.5k
    if (raw->max_total_in > 0) {
448
23.2k
        if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in))
449
4.58k
            bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in);
450
23.2k
    }
451
452
29.5k
    read = mz_stream_read(raw->stream.base, buf, bytes_to_read);
453
454
29.5k
    if (read > 0) {
455
22.7k
        raw->total_in += read;
456
22.7k
        raw->total_out += read;
457
22.7k
    }
458
459
29.5k
    return read;
460
29.5k
}
461
462
382
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size) {
463
382
    mz_stream_raw *raw = (mz_stream_raw *)stream;
464
382
    int32_t written = 0;
465
466
382
    written = mz_stream_write(raw->stream.base, buf, size);
467
468
382
    if (written > 0) {
469
382
        raw->total_out += written;
470
382
        raw->total_in += written;
471
382
    }
472
473
382
    return written;
474
382
}
475
476
0
int64_t mz_stream_raw_tell(void *stream) {
477
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
478
0
    return mz_stream_tell(raw->stream.base);
479
0
}
480
481
0
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin) {
482
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
483
0
    return mz_stream_seek(raw->stream.base, offset, origin);
484
0
}
485
486
23.7k
int32_t mz_stream_raw_close(void *stream) {
487
23.7k
    MZ_UNUSED(stream);
488
23.7k
    return MZ_OK;
489
23.7k
}
490
491
0
int32_t mz_stream_raw_error(void *stream) {
492
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
493
0
    return mz_stream_error(raw->stream.base);
494
0
}
495
496
39.5k
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
497
39.5k
    mz_stream_raw *raw = (mz_stream_raw *)stream;
498
39.5k
    switch (prop) {
499
23.7k
    case MZ_STREAM_PROP_TOTAL_IN:
500
23.7k
        *value = raw->total_in;
501
23.7k
        return MZ_OK;
502
368
    case MZ_STREAM_PROP_TOTAL_OUT:
503
368
        *value = raw->total_out;
504
368
        return MZ_OK;
505
39.5k
    }
506
15.4k
    return MZ_EXIST_ERROR;
507
39.5k
}
508
509
31.4k
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value) {
510
31.4k
    mz_stream_raw *raw = (mz_stream_raw *)stream;
511
31.4k
    switch (prop) {
512
31.1k
    case MZ_STREAM_PROP_TOTAL_IN_MAX:
513
31.1k
        raw->max_total_in = value;
514
31.1k
        return MZ_OK;
515
31.4k
    }
516
368
    return MZ_EXIST_ERROR;
517
31.4k
}
518
519
/***************************************************************************/
520
521
static mz_stream_vtbl mz_stream_raw_vtbl = {
522
    mz_stream_raw_open,   mz_stream_raw_is_open, mz_stream_raw_read,           mz_stream_raw_write,
523
    mz_stream_raw_tell,   mz_stream_raw_seek,    mz_stream_raw_close,          mz_stream_raw_error,
524
    mz_stream_raw_create, mz_stream_raw_delete,  mz_stream_raw_get_prop_int64, mz_stream_raw_set_prop_int64};
525
526
/***************************************************************************/
527
528
31.6k
void *mz_stream_raw_create(void) {
529
31.6k
    mz_stream_raw *raw = (mz_stream_raw *)calloc(1, sizeof(mz_stream_raw));
530
31.6k
    if (raw)
531
31.6k
        raw->stream.vtbl = &mz_stream_raw_vtbl;
532
31.6k
    return raw;
533
31.6k
}
534
535
31.6k
void mz_stream_raw_delete(void **stream) {
536
31.6k
    mz_stream_raw *raw = NULL;
537
31.6k
    if (!stream)
538
0
        return;
539
31.6k
    raw = (mz_stream_raw *)*stream;
540
31.6k
    free(raw);
541
31.6k
    *stream = NULL;
542
31.6k
}