1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file block_buffer_decoder.c 6 /// \brief Single-call .xz Block decoder 7 // 8 // Author: Lasse Collin 9 // 10 /////////////////////////////////////////////////////////////////////////////// 11 12 #include "block_decoder.h" 13 14 15 extern LZMA_API(lzma_ret) 16 lzma_block_buffer_decode(lzma_block *block, const lzma_allocator *allocator, 17 const uint8_t *in, size_t *in_pos, size_t in_size, 18 uint8_t *out, size_t *out_pos, size_t out_size) 19 { 20 if (in_pos == NULL || (in == NULL && *in_pos != in_size) 21 || *in_pos > in_size || out_pos == NULL 22 || (out == NULL && *out_pos != out_size) 23 || *out_pos > out_size) 24 return LZMA_PROG_ERROR; 25 26 // Initialize the Block decoder. 27 lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT; 28 lzma_ret ret = lzma_block_decoder_init( 29 &block_decoder, allocator, block); 30 31 if (ret == LZMA_OK) { 32 // Save the positions so that we can restore them in case 33 // an error occurs. 34 const size_t in_start = *in_pos; 35 const size_t out_start = *out_pos; 36 37 // Do the actual decoding. 38 ret = block_decoder.code(block_decoder.coder, allocator, 39 in, in_pos, in_size, out, out_pos, out_size, 40 LZMA_FINISH); 41 42 if (ret == LZMA_STREAM_END) { 43 ret = LZMA_OK; 44 } else { 45 if (ret == LZMA_OK) { 46 // Either the input was truncated or the 47 // output buffer was too small. 48 assert(*in_pos == in_size 49 || *out_pos == out_size); 50 51 // If all the input was consumed, then the 52 // input is truncated, even if the output 53 // buffer is also full. This is because 54 // processing the last byte of the Block 55 // never produces output. 56 // 57 // NOTE: This assumption may break when new 58 // filters are added, if the end marker of 59 // the filter doesn't consume at least one 60 // complete byte. 61 if (*in_pos == in_size) 62 ret = LZMA_DATA_ERROR; 63 else 64 ret = LZMA_BUF_ERROR; 65 } 66 67 // Restore the positions. 68 *in_pos = in_start; 69 *out_pos = out_start; 70 } 71 } 72 73 // Free the decoder memory. This needs to be done even if 74 // initialization fails, because the internal API doesn't 75 // require the initialization function to free its memory on error. 76 lzma_next_end(&block_decoder, allocator); 77 78 return ret; 79 } 80