Coverage Report

Created: 2023-11-14 06:59

/src/xz/tests/ossfuzz/fuzz.c
Line
Count
Source (jump to first uncovered line)
1
///////////////////////////////////////////////////////////////////////////////
2
//
3
/// \file       fuzz.c
4
/// \brief      Fuzz test program for liblzma
5
//
6
//  Author:     Lasse Collin
7
//
8
//  This file has been put into the public domain.
9
//  You can do whatever you want with this file.
10
//
11
///////////////////////////////////////////////////////////////////////////////
12
13
#include <inttypes.h>
14
#include <stdlib.h>
15
#include <stdio.h>
16
#include "lzma.h"
17
18
19
// Output buffer for decompressed data. This is write only; nothing cares
20
// about the actual data written here.
21
static uint8_t outbuf[4096];
22
23
24
extern int
25
LLVMFuzzerTestOneInput(const uint8_t *inbuf, size_t inbuf_size)
26
10.2k
{
27
  // Some header values can make liblzma allocate a lot of RAM
28
  // (up to about 4 GiB with liblzma 5.2.x). We set a limit here to
29
  // prevent extreme allocations when fuzzing.
30
10.2k
  const uint64_t memlimit = 300 << 20; // 300 MiB
31
32
  // Initialize a .xz decoder using the above memory usage limit.
33
  // Enable support for concatenated .xz files which is used when
34
  // decompressing regular .xz files (instead of data embedded inside
35
  // some other file format). Integrity checks on the uncompressed
36
  // data are ignored to make fuzzing more effective (incorrect check
37
  // values won't prevent the decoder from processing more input).
38
  //
39
  // The flag LZMA_IGNORE_CHECK doesn't disable verification of header
40
  // CRC32 values. Those checks are disabled when liblzma is built
41
  // with the #define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION.
42
10.2k
  lzma_stream strm = LZMA_STREAM_INIT;
43
10.2k
  lzma_ret ret = lzma_stream_decoder(&strm, memlimit,
44
10.2k
      LZMA_CONCATENATED | LZMA_IGNORE_CHECK);
45
10.2k
  if (ret != LZMA_OK) {
46
    // This should never happen unless the system has
47
    // no free memory or address space to allow the small
48
    // allocations that the initialization requires.
49
0
    fprintf(stderr, "lzma_stream_decoder() failed (%d)\n", ret);
50
0
    abort();
51
0
  }
52
53
  // Give the whole input buffer at once to liblzma.
54
  // Output buffer isn't initialized as liblzma only writes to it.
55
10.2k
  strm.next_in = inbuf;
56
10.2k
  strm.avail_in = inbuf_size;
57
10.2k
  strm.next_out = outbuf;
58
10.2k
  strm.avail_out = sizeof(outbuf);
59
60
51.0k
  while ((ret = lzma_code(&strm, LZMA_FINISH)) == LZMA_OK) {
61
40.8k
    if (strm.avail_out == 0) {
62
      // outbuf became full. We don't care about the
63
      // uncompressed data there, so we simply reuse
64
      // the outbuf and overwrite the old data.
65
26.8k
      strm.next_out = outbuf;
66
26.8k
      strm.avail_out = sizeof(outbuf);
67
26.8k
    }
68
40.8k
  }
69
70
  // LZMA_PROG_ERROR should never happen as long as the code calling
71
  // the liblzma functions is correct. Thus LZMA_PROG_ERROR is a sign
72
  // of a bug in either this function or in liblzma.
73
10.2k
  if (ret == LZMA_PROG_ERROR) {
74
0
    fprintf(stderr, "lzma_code() returned LZMA_PROG_ERROR\n");
75
0
    abort();
76
0
  }
77
78
  // Free the allocated memory.
79
10.2k
  lzma_end(&strm);
80
81
10.2k
  return 0;
82
10.2k
}