Coverage Report

Created: 2026-05-11 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/tests/gtest/avif_fuzztest_dec.cc
Line
Count
Source
1
// Copyright 2023 Google LLC
2
// SPDX-License-Identifier: BSD-2-Clause
3
// Decodes an arbitrary sequence of bytes.
4
5
#include <algorithm>
6
#include <cstdint>
7
#include <limits>
8
9
#include "avif/avif.h"
10
#include "avif_fuzztest_helpers.h"
11
#include "aviftest_helpers.h"
12
#include "fuzztest/fuzztest.h"
13
#include "gtest/gtest.h"
14
15
using ::fuzztest::Arbitrary;
16
17
namespace avif {
18
namespace testutil {
19
namespace {
20
21
//------------------------------------------------------------------------------
22
23
void Parse(const std::string& arbitrary_bytes, bool is_persistent,
24
8.23k
           DecoderPtr decoder) {
25
8.23k
  ASSERT_FALSE(GetSeedDataDirs().empty());  // Make sure seeds are available.
26
27
8.23k
  const uint8_t* data =
28
8.23k
      reinterpret_cast<const uint8_t*>(arbitrary_bytes.data());
29
8.23k
  avifIO* const io = avifIOCreateMemoryReader(data, arbitrary_bytes.size());
30
8.23k
  if (io == nullptr) return;
31
8.23k
  io->persistent = is_persistent;
32
8.23k
  avifDecoderSetIO(decoder.get(), io);
33
  // No need to worry about decoding taking too much time or memory because
34
  // this test only exercises parsing.
35
8.23k
  decoder->imageSizeLimit = AVIF_DEFAULT_IMAGE_SIZE_LIMIT;
36
8.23k
  decoder->imageDimensionLimit = std::numeric_limits<uint32_t>::max();
37
8.23k
  decoder->imageCountLimit = 0;
38
39
  // AVIF_RESULT_INTERNAL_ERROR means a broken invariant and should not happen.
40
8.23k
  ASSERT_NE(avifDecoderParse(decoder.get()), AVIF_RESULT_INTERNAL_ERROR);
41
8.23k
}
42
43
FUZZ_TEST(ParseAvifTest, Parse)
44
    .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_AVIF}),
45
                 /*is_persistent=*/Arbitrary<bool>(),
46
                 ArbitraryAvifDecoderPossiblyNoContent());
47
48
//------------------------------------------------------------------------------
49
50
void Decode(const std::string& arbitrary_bytes, bool is_persistent,
51
20.5k
            DecoderPtr decoder) {
52
20.5k
  ASSERT_FALSE(GetSeedDataDirs().empty());  // Make sure seeds are available.
53
54
20.5k
  const uint8_t* data =
55
20.5k
      reinterpret_cast<const uint8_t*>(arbitrary_bytes.data());
56
20.5k
  avifIO* const io = avifIOCreateMemoryReader(data, arbitrary_bytes.size());
57
20.5k
  if (io == nullptr) return;
58
  // The Chrome's avifIO object is not persistent.
59
20.5k
  io->persistent = is_persistent;
60
20.5k
  avifDecoderSetIO(decoder.get(), io);
61
62
20.5k
  avifResult result = avifDecoderParse(decoder.get());
63
  // AVIF_RESULT_INTERNAL_ERROR means a broken invariant and should not happen.
64
20.5k
  ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR);
65
20.5k
  if (result != AVIF_RESULT_OK) return;
66
67
30.7k
  for (size_t i = 0; i < decoder->image->numProperties; ++i) {
68
12.8k
    const avifRWData& box_payload = decoder->image->properties[i].boxPayload;
69
    // Each custom property should be found as is in the input bitstream.
70
12.8k
    EXPECT_NE(std::search(data, data + arbitrary_bytes.size(), box_payload.data,
71
12.8k
                          box_payload.data + box_payload.size),
72
12.8k
              data + arbitrary_bytes.size());
73
12.8k
  }
74
75
23.4k
  while ((result = avifDecoderNextImage(decoder.get())) == AVIF_RESULT_OK) {
76
5.59k
    EXPECT_GT(decoder->image->width, 0u);
77
5.59k
    EXPECT_GT(decoder->image->height, 0u);
78
5.59k
  }
79
17.8k
  ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR);
80
81
  // Loop once.
82
17.8k
  result = avifDecoderReset(decoder.get());
83
17.8k
  ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR);
84
17.8k
  if (result != AVIF_RESULT_OK) return;
85
21.0k
  while ((result = avifDecoderNextImage(decoder.get())) == AVIF_RESULT_OK) {
86
4.53k
  }
87
  ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR);
88
16.4k
}
89
90
FUZZ_TEST(DecodeAvifTest, Decode)
91
    .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_AVIF}),
92
                 /*is_persistent=*/Arbitrary<bool>(),
93
                 ArbitraryAvifDecoderPossiblyNoContent());
94
95
//------------------------------------------------------------------------------
96
97
}  // namespace
98
}  // namespace testutil
99
}  // namespace avif