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