1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file filter_buffer_decoder.c 4/// \brief Single-call raw decoding 5// 6// Author: Lasse Collin 7// 8// This file has been put into the public domain. 9// You can do whatever you want with this file. 10// 11/////////////////////////////////////////////////////////////////////////////// 12 13#include "filter_decoder.h" 14 15 16extern LZMA_API(lzma_ret) 17lzma_raw_buffer_decode( 18 const lzma_filter *filters, const lzma_allocator *allocator, 19 const uint8_t *in, size_t *in_pos, size_t in_size, 20 uint8_t *out, size_t *out_pos, size_t out_size) 21{ 22 // Validate what isn't validated later in filter_common.c. 23 if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL 24 || out_pos == NULL || *out_pos > out_size) 25 return LZMA_PROG_ERROR; 26 27 // Initialize the decoer. 28 lzma_next_coder next = LZMA_NEXT_CODER_INIT; 29 return_if_error(lzma_raw_decoder_init(&next, allocator, filters)); 30 31 // Store the positions so that we can restore them if something 32 // goes wrong. 33 const size_t in_start = *in_pos; 34 const size_t out_start = *out_pos; 35 36 // Do the actual decoding and free decoder's memory. 37 lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size, 38 out, out_pos, out_size, LZMA_FINISH); 39 40 if (ret == LZMA_STREAM_END) { 41 ret = LZMA_OK; 42 } else { 43 if (ret == LZMA_OK) { 44 // Either the input was truncated or the 45 // output buffer was too small. 46 assert(*in_pos == in_size || *out_pos == out_size); 47 48 if (*in_pos != in_size) { 49 // Since input wasn't consumed completely, 50 // the output buffer became full and is 51 // too small. 52 ret = LZMA_BUF_ERROR; 53 54 } else if (*out_pos != out_size) { 55 // Since output didn't became full, the input 56 // has to be truncated. 57 ret = LZMA_DATA_ERROR; 58 59 } else { 60 // All the input was consumed and output 61 // buffer is full. Now we don't immediately 62 // know the reason for the error. Try 63 // decoding one more byte. If it succeeds, 64 // then the output buffer was too small. If 65 // we cannot get a new output byte, the input 66 // is truncated. 67 uint8_t tmp[1]; 68 size_t tmp_pos = 0; 69 (void)next.code(next.coder, allocator, 70 in, in_pos, in_size, 71 tmp, &tmp_pos, 1, LZMA_FINISH); 72 73 if (tmp_pos == 1) 74 ret = LZMA_BUF_ERROR; 75 else 76 ret = LZMA_DATA_ERROR; 77 } 78 } 79 80 // Restore the positions. 81 *in_pos = in_start; 82 *out_pos = out_start; 83 } 84 85 lzma_next_end(&next, allocator); 86 87 return ret; 88} 89