Index: xz/src/liblzma/common/filter_buffer_decoder.c |
=================================================================== |
--- xz/src/liblzma/common/filter_buffer_decoder.c (revision 0) |
+++ xz/src/liblzma/common/filter_buffer_decoder.c (revision 0) |
@@ -0,0 +1,87 @@ |
+/////////////////////////////////////////////////////////////////////////////// |
+// |
+/// \file filter_buffer_decoder.c |
+/// \brief Single-call raw decoding |
+// |
+// Author: Lasse Collin |
+// |
+// This file has been put into the public domain. |
+// You can do whatever you want with this file. |
+// |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+#include "filter_decoder.h" |
+ |
+ |
+extern LZMA_API(lzma_ret) |
+lzma_raw_buffer_decode(const lzma_filter *filters, lzma_allocator *allocator, |
+ const uint8_t *in, size_t *in_pos, size_t in_size, |
+ uint8_t *out, size_t *out_pos, size_t out_size) |
+{ |
+ // Validate what isn't validated later in filter_common.c. |
+ if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL |
+ || out_pos == NULL || *out_pos > out_size) |
+ return LZMA_PROG_ERROR; |
+ |
+ // Initialize the decoer. |
+ lzma_next_coder next = LZMA_NEXT_CODER_INIT; |
+ return_if_error(lzma_raw_decoder_init(&next, allocator, filters)); |
+ |
+ // Store the positions so that we can restore them if something |
+ // goes wrong. |
+ const size_t in_start = *in_pos; |
+ const size_t out_start = *out_pos; |
+ |
+ // Do the actual decoding and free decoder's memory. |
+ lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size, |
+ out, out_pos, out_size, LZMA_FINISH); |
+ |
+ if (ret == LZMA_STREAM_END) { |
+ ret = LZMA_OK; |
+ } else { |
+ if (ret == LZMA_OK) { |
+ // Either the input was truncated or the |
+ // output buffer was too small. |
+ assert(*in_pos == in_size || *out_pos == out_size); |
+ |
+ if (*in_pos != in_size) { |
+ // Since input wasn't consumed completely, |
+ // the output buffer became full and is |
+ // too small. |
+ ret = LZMA_BUF_ERROR; |
+ |
+ } else if (*out_pos != out_size) { |
+ // Since output didn't became full, the input |
+ // has to be truncated. |
+ ret = LZMA_DATA_ERROR; |
+ |
+ } else { |
+ // All the input was consumed and output |
+ // buffer is full. Now we don't immediately |
+ // know the reason for the error. Try |
+ // decoding one more byte. If it succeeds, |
+ // then the output buffer was too small. If |
+ // we cannot get a new output byte, the input |
+ // is truncated. |
+ uint8_t tmp[1]; |
+ size_t tmp_pos = 0; |
+ (void)next.code(next.coder, allocator, |
+ in, in_pos, in_size, |
+ tmp, &tmp_pos, 1, LZMA_FINISH); |
+ |
+ if (tmp_pos == 1) |
+ ret = LZMA_BUF_ERROR; |
+ else |
+ ret = LZMA_DATA_ERROR; |
+ } |
+ } |
+ |
+ // Restore the positions. |
+ *in_pos = in_start; |
+ *out_pos = out_start; |
+ } |
+ |
+ lzma_next_end(&next, allocator); |
+ |
+ return ret; |
+} |
Property changes on: xz/src/liblzma/common/filter_buffer_decoder.c |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |