Coverage Report

Created: 2025-06-22 08:04

/src/libjxl/lib/jxl/box_content_decoder.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 "lib/jxl/box_content_decoder.h"
7
8
#include <algorithm>
9
#include <cstddef>
10
#include <cstdint>
11
#include <cstring>
12
13
#include "lib/jxl/base/sanitizers.h"
14
15
namespace jxl {
16
17
40.1k
JxlBoxContentDecoder::JxlBoxContentDecoder() = default;
18
19
40.1k
JxlBoxContentDecoder::~JxlBoxContentDecoder() {
20
40.1k
  if (brotli_dec) {
21
1.10k
    BrotliDecoderDestroyInstance(brotli_dec);
22
1.10k
  }
23
40.1k
}
24
25
void JxlBoxContentDecoder::StartBox(bool brob_decode, bool box_until_eof,
26
47.0k
                                    size_t contents_size) {
27
47.0k
  if (brotli_dec) {
28
457
    BrotliDecoderDestroyInstance(brotli_dec);
29
457
    brotli_dec = nullptr;
30
457
  }
31
47.0k
  header_done_ = false;
32
47.0k
  brob_decode_ = brob_decode;
33
47.0k
  box_until_eof_ = box_until_eof;
34
47.0k
  remaining_ = box_until_eof ? 0 : contents_size;
35
47.0k
  pos_ = 0;
36
47.0k
}
37
38
JxlDecoderStatus JxlBoxContentDecoder::Process(const uint8_t* next_in,
39
                                               size_t avail_in, size_t box_pos,
40
                                               uint8_t** next_out,
41
12.7k
                                               size_t* avail_out) {
42
12.7k
  next_in += pos_ - box_pos;
43
12.7k
  avail_in -= pos_ - box_pos;
44
45
12.7k
  if (brob_decode_) {
46
10.7k
    if (!header_done_) {
47
1.56k
      if (avail_in < 4) return JXL_DEC_NEED_MORE_INPUT;
48
1.56k
      if (!box_until_eof_) {
49
869
        if (remaining_ < 4) return JXL_DEC_ERROR;
50
868
        remaining_ -= 4;
51
868
      }
52
1.56k
      next_in += 4;
53
1.56k
      avail_in -= 4;
54
1.56k
      pos_ += 4;
55
1.56k
      header_done_ = true;
56
1.56k
    }
57
58
10.7k
    if (!brotli_dec) {
59
1.56k
      brotli_dec = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
60
1.56k
    }
61
62
10.7k
    const uint8_t* next_in_before = next_in;
63
10.7k
    uint8_t* next_out_before = *next_out;
64
10.7k
    msan::MemoryIsInitialized(next_in, avail_in);
65
10.7k
    BrotliDecoderResult res = BrotliDecoderDecompressStream(
66
10.7k
        brotli_dec, &avail_in, &next_in, avail_out, next_out, nullptr);
67
10.7k
    size_t consumed = next_in - next_in_before;
68
10.7k
    size_t produced = *next_out - next_out_before;
69
10.7k
    if (res == BROTLI_DECODER_RESULT_ERROR) {
70
536
      return JXL_DEC_ERROR;
71
536
    }
72
10.2k
    msan::UnpoisonMemory(next_out_before, produced);
73
10.2k
    pos_ += consumed;
74
10.2k
    if (!box_until_eof_) remaining_ -= consumed;
75
10.2k
    if (res == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
76
968
      return JXL_DEC_NEED_MORE_INPUT;
77
968
    }
78
9.25k
    if (res == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
79
9.20k
      return JXL_DEC_BOX_NEED_MORE_OUTPUT;
80
9.20k
    }
81
48
    if (res == BROTLI_DECODER_RESULT_SUCCESS) {
82
48
      return JXL_DEC_BOX_COMPLETE;
83
48
    }
84
    // unknown Brotli result
85
0
    return JXL_DEC_ERROR;
86
1.96k
  } else {
87
    // remaining box bytes as seen from dec->file_pos
88
1.96k
    size_t can_read = avail_in;
89
1.96k
    if (!box_until_eof_) can_read = std::min<size_t>(can_read, remaining_);
90
1.96k
    size_t to_write = std::min<size_t>(can_read, *avail_out);
91
1.96k
    memcpy(*next_out, next_in, to_write);
92
93
1.96k
    *next_out += to_write;
94
1.96k
    *avail_out -= to_write;
95
1.96k
    if (!box_until_eof_) remaining_ -= to_write;
96
1.96k
    pos_ += to_write;
97
98
1.96k
    if (to_write < can_read) return JXL_DEC_BOX_NEED_MORE_OUTPUT;
99
100
1.05k
    if (!box_until_eof_ && remaining_ > 0) return JXL_DEC_NEED_MORE_INPUT;
101
102
1.04k
    return JXL_DEC_BOX_COMPLETE;
103
1.05k
  }
104
12.7k
}
105
106
}  // namespace jxl