7#include "core/fxcodec/gif/lzw_decompressor.h"
14#include "core/fxcrt/compiler_specific.h"
15#include "core/fxcrt/fx_safe_types.h"
16#include "core/fxcrt/numerics/safe_conversions.h"
17#include "core/fxcrt/ptr_util.h"
18#include "core/fxcrt/stl_util.h"
34 : code_size_(code_exp),
35 code_color_end_(
static_cast<uint16_t>(1 << (color_exp + 1))),
36 code_clear_(
static_cast<uint16_t>(1 << code_exp)),
37 code_end_(
static_cast<uint16_t>((1 << code_exp) + 1)) {
44 uint32_t* dest_size) {
45 if (!dest_buf || !dest_size) {
49 if (avail_input_.empty()) {
57 if (decompressed_next_ != 0) {
58 size_t extracted_size =
59 ExtractData(
UNSAFE_TODO(pdfium::make_span(dest_buf, *dest_size)));
60 if (decompressed_next_ != 0)
67 while (i.ValueOrDie() <= *dest_size &&
68 (!avail_input_.empty() || bits_left_ >= code_size_cur_)) {
72 if (!avail_input_.empty()) {
77 safe_code <<= bits_left_;
78 safe_code |= code_store_;
79 if (!safe_code.IsValid())
82 code_store_ = safe_code.ValueOrDie();
83 avail_input_ = avail_input_.subspan(1u);
87 while (bits_left_ >= code_size_cur_) {
89 static_cast<uint16_t>(code_store_) & ((1 << code_size_cur_) - 1);
90 code_store_ >>= code_size_cur_;
91 bits_left_ -= code_size_cur_;
92 if (code == code_clear_) {
96 if (code == code_end_) {
97 *dest_size = i.ValueOrDie();
101 if (code_old_ !=
static_cast<uint16_t>(-1)) {
103 if (code == code_next_) {
104 AddCode(code_old_, code_first_);
105 if (!DecodeString(code))
107 }
else if (code > code_next_) {
110 if (!DecodeString(code))
113 uint8_t append_char = decompressed_[decompressed_next_ - 1];
114 AddCode(code_old_, append_char);
118 if (!DecodeString(code))
124 pdfium::make_span(dest_buf, (*dest_size - i).ValueOrDie())));
125 if (decompressed_next_ != 0) {
133 if (!avail_input_.empty()) {
136 *dest_size = i.ValueOrDie();
141 code_size_cur_ = code_size_ + 1;
142 code_next_ = code_end_ + 1;
143 code_old_ =
static_cast<uint16_t>(-1);
144 fxcrt::Fill(code_table_, CodeEntry{});
145 static_assert(std::is_aggregate_v<CodeEntry>);
146 for (uint16_t i = 0; i < code_clear_; i++) {
147 code_table_[i].suffix =
static_cast<uint8_t>(i);
149 decompressed_.resize(code_next_ - code_clear_ + 1);
150 decompressed_next_ = 0;
153void LZWDecompressor::AddCode(uint16_t prefix_code, uint8_t append_char) {
157 code_table_[code_next_].prefix = prefix_code;
158 code_table_[code_next_].suffix = append_char;
160 if (code_next_ >> code_size_cur_)
166 decompressed_.resize(code_next_ - code_clear_ + 1);
167 decompressed_next_ = 0;
169 while (code >= code_clear_ && code <= code_next_) {
170 if (code == code_table_[code].prefix ||
171 decompressed_next_ >= decompressed_.size())
174 decompressed_[decompressed_next_++] = code_table_[code].suffix;
175 code = code_table_[code].prefix;
178 if (code >= code_color_end_)
181 decompressed_[decompressed_next_++] =
static_cast<uint8_t>(code);
182 code_first_ =
static_cast<uint8_t>(code);
187 if (dest_span.empty()) {
190 size_t copy_size = std::min(dest_span.size(), decompressed_next_);
192 decompressed_.data() + decompressed_next_ - copy_size,
193 decompressed_.data() + decompressed_next_, dest_span.data()));
194 decompressed_next_ -= copy_size;
UNSAFE_BUFFER_USAGE Status Decode(uint8_t *dest_buf, uint32_t *dest_size)
pdfium::CheckedNumeric< uint32_t > FX_SAFE_UINT32