Coverage Report

Created: 2025-07-23 07:47

/src/libjxl/tools/rans_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
6
#include <jxl/memory_manager.h>
7
8
#include <cstddef>
9
#include <cstdint>
10
#include <cstdio>
11
#include <vector>
12
13
#include "lib/jxl/base/common.h"
14
#include "lib/jxl/base/compiler_specific.h"
15
#include "lib/jxl/base/span.h"
16
#include "lib/jxl/base/status.h"
17
#include "lib/jxl/dec_ans.h"
18
#include "lib/jxl/dec_bit_reader.h"
19
#include "lib/jxl/fuzztest.h"
20
#include "tools/tracking_memory_manager.h"
21
22
namespace {
23
24
using ::jpegxl::tools::kGiB;
25
using ::jpegxl::tools::TrackingMemoryManager;
26
using ::jxl::ANSCode;
27
using ::jxl::ANSSymbolReader;
28
using ::jxl::BitReader;
29
using ::jxl::BitReaderScopedCloser;
30
using ::jxl::Bytes;
31
using ::jxl::Status;
32
33
2.12k
void CheckImpl(bool ok, const char* conndition, const char* file, int line) {
34
2.12k
  if (!ok) {
35
0
    fprintf(stderr, "Check(%s) failed at %s:%d\n", conndition, file, line);
36
0
    JXL_CRASH();
37
0
  }
38
2.12k
}
39
2.12k
#define Check(OK) CheckImpl((OK), #OK, __FILE__, __LINE__)
40
41
Status Run(const uint8_t* data, size_t size, JxlMemoryManager* memory_manager,
42
2.12k
           size_t num_contexts) {
43
2.12k
  std::vector<uint8_t> context_map;
44
2.12k
  Status ret = true;
45
2.12k
  {
46
2.12k
    BitReader br(Bytes(data, size));
47
2.12k
    BitReaderScopedCloser br_closer(br, ret);
48
2.12k
    ANSCode code;
49
2.12k
    JXL_RETURN_IF_ERROR(DecodeHistograms(memory_manager, &br, num_contexts,
50
2.12k
                                         &code, &context_map));
51
1.43k
    JXL_ASSIGN_OR_RETURN(ANSSymbolReader ansreader,
52
1.43k
                         ANSSymbolReader::Create(&code, &br));
53
54
    // Limit the maximum amount of reads to avoid (valid) infinite loops.
55
1.43k
    const size_t maxreads = size * 8;
56
1.43k
    size_t numreads = 0;
57
1.43k
    int context = 0;
58
74.9M
    while (jxl::DivCeil(br.TotalBitsConsumed(), jxl::kBitsPerByte) < size &&
59
74.9M
           numreads <= maxreads) {
60
74.9M
      int code = ansreader.ReadHybridUint(context, &br, context_map);
61
74.9M
      context = code % num_contexts;
62
74.9M
      numreads++;
63
74.9M
    }
64
1.43k
  }
65
0
  return true;
66
1.43k
}
67
68
2.12k
int DoTestOneInput(const uint8_t* data, size_t size) {
69
2.12k
  if (size < 2) return 0;
70
2.12k
  size_t numContexts = data[0] * 256 * data[1] + 1;
71
2.12k
  data += 2;
72
2.12k
  size -= 2;
73
74
2.12k
  TrackingMemoryManager memory_manager{/* cap */ 1 * kGiB,
75
2.12k
                                       /* total_cap */ 5 * kGiB};
76
  // It is OK to fail.
77
2.12k
  (void)Run(data, size, memory_manager.get(), numContexts);
78
2.12k
  Check(memory_manager.Reset());
79
80
2.12k
  return 0;
81
2.12k
}
82
83
}  // namespace
84
85
69.7k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
86
69.7k
  return DoTestOneInput(data, size);
87
69.7k
}
88
89
0
void TestOneInput(const std::vector<uint8_t>& data) {
90
0
  DoTestOneInput(data.data(), data.size());
91
0
}
92
93
FUZZ_TEST(RansFuzzTest, TestOneInput);