root/src/liblzma/common/filter_buffer_decoder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. LZMA_API

///////////////////////////////////////////////////////////////////////////////
//
/// \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;
}

/* [<][>][^][v][top][bottom][index][help] */