/src/xz/tests/ossfuzz/fuzz_common.h
Line | Count | Source |
1 | | // SPDX-License-Identifier: 0BSD |
2 | | |
3 | | /////////////////////////////////////////////////////////////////////////////// |
4 | | // |
5 | | /// \file fuzz_common.h |
6 | | /// \brief Common macros and functions needed by the fuzz targets |
7 | | // |
8 | | // Authors: Maksym Vatsyk |
9 | | // Lasse Collin |
10 | | // |
11 | | /////////////////////////////////////////////////////////////////////////////// |
12 | | |
13 | | #include <inttypes.h> |
14 | | #include <stdlib.h> |
15 | | #include <stdio.h> |
16 | | #include "lzma.h" |
17 | | |
18 | | // Some header values can make liblzma allocate a lot of RAM |
19 | | // (up to about 4 GiB with liblzma 5.2.x). We set a limit here to |
20 | | // prevent extreme allocations when fuzzing. |
21 | 53.3k | #define MEM_LIMIT (300 << 20) // 300 MiB |
22 | | |
23 | | // Amount of input to pass to lzma_code() per call at most. |
24 | 78.0k | #define IN_CHUNK_SIZE 2047 |
25 | | |
26 | | |
27 | | static void |
28 | 17.3k | fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { |
29 | | // Output buffer for decompressed data. This is write only; nothing |
30 | | // cares about the actual data written here. |
31 | 17.3k | uint8_t outbuf[4096]; |
32 | | |
33 | | // Pass half of the input on the first call and then proceed in |
34 | | // chunks. It's fine that this rounds to 0 when inbuf_size is 1. |
35 | 17.3k | stream->next_in = inbuf; |
36 | 17.3k | stream->avail_in = inbuf_size / 2; |
37 | | |
38 | 17.3k | lzma_action action = LZMA_RUN; |
39 | | |
40 | 17.3k | lzma_ret ret; |
41 | 414k | do { |
42 | 414k | if (stream->avail_in == 0 && inbuf_size > 0) { |
43 | 47.3k | const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE |
44 | 47.3k | ? inbuf_size : IN_CHUNK_SIZE; |
45 | | |
46 | 47.3k | stream->next_in = inbuf; |
47 | 47.3k | stream->avail_in = chunk_size; |
48 | | |
49 | 47.3k | inbuf += chunk_size; |
50 | 47.3k | inbuf_size -= chunk_size; |
51 | | |
52 | 47.3k | if (inbuf_size == 0) |
53 | 16.6k | action = LZMA_FINISH; |
54 | 47.3k | } |
55 | | |
56 | 414k | if (stream->avail_out == 0) { |
57 | | // outbuf became full. We don't care about the |
58 | | // uncompressed data there, so we simply reuse |
59 | | // the outbuf and overwrite the old data. |
60 | 358k | stream->next_out = outbuf; |
61 | 358k | stream->avail_out = sizeof(outbuf); |
62 | 358k | } |
63 | 414k | } while ((ret = lzma_code(stream, action)) == LZMA_OK); |
64 | | |
65 | | // LZMA_PROG_ERROR should never happen as long as the code calling |
66 | | // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign |
67 | | // of a bug in either this function or in liblzma. |
68 | 17.3k | if (ret == LZMA_PROG_ERROR) { |
69 | | fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); |
70 | 0 | abort(); |
71 | 0 | } |
72 | 17.3k | } fuzz_decode_stream_mt.c:fuzz_code Line | Count | Source | 28 | 5.49k | fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { | 29 | | // Output buffer for decompressed data. This is write only; nothing | 30 | | // cares about the actual data written here. | 31 | 5.49k | uint8_t outbuf[4096]; | 32 | | | 33 | | // Pass half of the input on the first call and then proceed in | 34 | | // chunks. It's fine that this rounds to 0 when inbuf_size is 1. | 35 | 5.49k | stream->next_in = inbuf; | 36 | 5.49k | stream->avail_in = inbuf_size / 2; | 37 | | | 38 | 5.49k | lzma_action action = LZMA_RUN; | 39 | | | 40 | 5.49k | lzma_ret ret; | 41 | 76.1k | do { | 42 | 76.1k | if (stream->avail_in == 0 && inbuf_size > 0) { | 43 | 22.4k | const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE | 44 | 22.4k | ? inbuf_size : IN_CHUNK_SIZE; | 45 | | | 46 | 22.4k | stream->next_in = inbuf; | 47 | 22.4k | stream->avail_in = chunk_size; | 48 | | | 49 | 22.4k | inbuf += chunk_size; | 50 | 22.4k | inbuf_size -= chunk_size; | 51 | | | 52 | 22.4k | if (inbuf_size == 0) | 53 | 5.18k | action = LZMA_FINISH; | 54 | 22.4k | } | 55 | | | 56 | 76.1k | if (stream->avail_out == 0) { | 57 | | // outbuf became full. We don't care about the | 58 | | // uncompressed data there, so we simply reuse | 59 | | // the outbuf and overwrite the old data. | 60 | 50.9k | stream->next_out = outbuf; | 61 | 50.9k | stream->avail_out = sizeof(outbuf); | 62 | 50.9k | } | 63 | 76.1k | } while ((ret = lzma_code(stream, action)) == LZMA_OK); | 64 | | | 65 | | // LZMA_PROG_ERROR should never happen as long as the code calling | 66 | | // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign | 67 | | // of a bug in either this function or in liblzma. | 68 | 5.49k | if (ret == LZMA_PROG_ERROR) { | 69 | | fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); | 70 | 0 | abort(); | 71 | 0 | } | 72 | 5.49k | } |
fuzz_decode_stream.c:fuzz_code Line | Count | Source | 28 | 4.70k | fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { | 29 | | // Output buffer for decompressed data. This is write only; nothing | 30 | | // cares about the actual data written here. | 31 | 4.70k | uint8_t outbuf[4096]; | 32 | | | 33 | | // Pass half of the input on the first call and then proceed in | 34 | | // chunks. It's fine that this rounds to 0 when inbuf_size is 1. | 35 | 4.70k | stream->next_in = inbuf; | 36 | 4.70k | stream->avail_in = inbuf_size / 2; | 37 | | | 38 | 4.70k | lzma_action action = LZMA_RUN; | 39 | | | 40 | 4.70k | lzma_ret ret; | 41 | 55.6k | do { | 42 | 55.6k | if (stream->avail_in == 0 && inbuf_size > 0) { | 43 | 17.5k | const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE | 44 | 17.5k | ? inbuf_size : IN_CHUNK_SIZE; | 45 | | | 46 | 17.5k | stream->next_in = inbuf; | 47 | 17.5k | stream->avail_in = chunk_size; | 48 | | | 49 | 17.5k | inbuf += chunk_size; | 50 | 17.5k | inbuf_size -= chunk_size; | 51 | | | 52 | 17.5k | if (inbuf_size == 0) | 53 | 4.35k | action = LZMA_FINISH; | 54 | 17.5k | } | 55 | | | 56 | 55.6k | if (stream->avail_out == 0) { | 57 | | // outbuf became full. We don't care about the | 58 | | // uncompressed data there, so we simply reuse | 59 | | // the outbuf and overwrite the old data. | 60 | 35.3k | stream->next_out = outbuf; | 61 | 35.3k | stream->avail_out = sizeof(outbuf); | 62 | 35.3k | } | 63 | 55.6k | } while ((ret = lzma_code(stream, action)) == LZMA_OK); | 64 | | | 65 | | // LZMA_PROG_ERROR should never happen as long as the code calling | 66 | | // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign | 67 | | // of a bug in either this function or in liblzma. | 68 | 4.70k | if (ret == LZMA_PROG_ERROR) { | 69 | | fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); | 70 | 0 | abort(); | 71 | 0 | } | 72 | 4.70k | } |
fuzz_decode_alone.c:fuzz_code Line | Count | Source | 28 | 3.14k | fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { | 29 | | // Output buffer for decompressed data. This is write only; nothing | 30 | | // cares about the actual data written here. | 31 | 3.14k | uint8_t outbuf[4096]; | 32 | | | 33 | | // Pass half of the input on the first call and then proceed in | 34 | | // chunks. It's fine that this rounds to 0 when inbuf_size is 1. | 35 | 3.14k | stream->next_in = inbuf; | 36 | 3.14k | stream->avail_in = inbuf_size / 2; | 37 | | | 38 | 3.14k | lzma_action action = LZMA_RUN; | 39 | | | 40 | 3.14k | lzma_ret ret; | 41 | 274k | do { | 42 | 274k | if (stream->avail_in == 0 && inbuf_size > 0) { | 43 | 3.16k | const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE | 44 | 3.16k | ? inbuf_size : IN_CHUNK_SIZE; | 45 | | | 46 | 3.16k | stream->next_in = inbuf; | 47 | 3.16k | stream->avail_in = chunk_size; | 48 | | | 49 | 3.16k | inbuf += chunk_size; | 50 | 3.16k | inbuf_size -= chunk_size; | 51 | | | 52 | 3.16k | if (inbuf_size == 0) | 53 | 3.10k | action = LZMA_FINISH; | 54 | 3.16k | } | 55 | | | 56 | 274k | if (stream->avail_out == 0) { | 57 | | // outbuf became full. We don't care about the | 58 | | // uncompressed data there, so we simply reuse | 59 | | // the outbuf and overwrite the old data. | 60 | 268k | stream->next_out = outbuf; | 61 | 268k | stream->avail_out = sizeof(outbuf); | 62 | 268k | } | 63 | 274k | } while ((ret = lzma_code(stream, action)) == LZMA_OK); | 64 | | | 65 | | // LZMA_PROG_ERROR should never happen as long as the code calling | 66 | | // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign | 67 | | // of a bug in either this function or in liblzma. | 68 | 3.14k | if (ret == LZMA_PROG_ERROR) { | 69 | | fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); | 70 | 0 | abort(); | 71 | 0 | } | 72 | 3.14k | } |
fuzz_encode_stream.c:fuzz_code Line | Count | Source | 28 | 3.99k | fuzz_code(lzma_stream *stream, const uint8_t *inbuf, size_t inbuf_size) { | 29 | | // Output buffer for decompressed data. This is write only; nothing | 30 | | // cares about the actual data written here. | 31 | 3.99k | uint8_t outbuf[4096]; | 32 | | | 33 | | // Pass half of the input on the first call and then proceed in | 34 | | // chunks. It's fine that this rounds to 0 when inbuf_size is 1. | 35 | 3.99k | stream->next_in = inbuf; | 36 | 3.99k | stream->avail_in = inbuf_size / 2; | 37 | | | 38 | 3.99k | lzma_action action = LZMA_RUN; | 39 | | | 40 | 3.99k | lzma_ret ret; | 41 | 8.22k | do { | 42 | 8.22k | if (stream->avail_in == 0 && inbuf_size > 0) { | 43 | 4.20k | const size_t chunk_size = inbuf_size < IN_CHUNK_SIZE | 44 | 4.20k | ? inbuf_size : IN_CHUNK_SIZE; | 45 | | | 46 | 4.20k | stream->next_in = inbuf; | 47 | 4.20k | stream->avail_in = chunk_size; | 48 | | | 49 | 4.20k | inbuf += chunk_size; | 50 | 4.20k | inbuf_size -= chunk_size; | 51 | | | 52 | 4.20k | if (inbuf_size == 0) | 53 | 3.98k | action = LZMA_FINISH; | 54 | 4.20k | } | 55 | | | 56 | 8.22k | if (stream->avail_out == 0) { | 57 | | // outbuf became full. We don't care about the | 58 | | // uncompressed data there, so we simply reuse | 59 | | // the outbuf and overwrite the old data. | 60 | 4.01k | stream->next_out = outbuf; | 61 | 4.01k | stream->avail_out = sizeof(outbuf); | 62 | 4.01k | } | 63 | 8.22k | } while ((ret = lzma_code(stream, action)) == LZMA_OK); | 64 | | | 65 | | // LZMA_PROG_ERROR should never happen as long as the code calling | 66 | | // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign | 67 | | // of a bug in either this function or in liblzma. | 68 | 3.99k | if (ret == LZMA_PROG_ERROR) { | 69 | | fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n"); | 70 | 0 | abort(); | 71 | 0 | } | 72 | 3.99k | } |
|