]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/xz/src/liblzma/common/vli_decoder.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / xz / src / liblzma / common / vli_decoder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       vli_decoder.c
4 /// \brief      Decodes variable-length integers
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 "common.h"
14
15
16 extern LZMA_API(lzma_ret)
17 lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
18                 const uint8_t *restrict in, size_t *restrict in_pos,
19                 size_t in_size)
20 {
21         // If we haven't been given vli_pos, work in single-call mode.
22         size_t vli_pos_internal = 0;
23         if (vli_pos == NULL) {
24                 vli_pos = &vli_pos_internal;
25                 *vli = 0;
26
27                 // If there's no input, use LZMA_DATA_ERROR. This way it is
28                 // easy to decode VLIs from buffers that have known size,
29                 // and get the correct error code in case the buffer is
30                 // too short.
31                 if (*in_pos >= in_size)
32                         return LZMA_DATA_ERROR;
33
34         } else {
35                 // Initialize *vli when starting to decode a new integer.
36                 if (*vli_pos == 0)
37                         *vli = 0;
38
39                 // Validate the arguments.
40                 if (*vli_pos >= LZMA_VLI_BYTES_MAX
41                                 || (*vli >> (*vli_pos * 7)) != 0)
42                         return LZMA_PROG_ERROR;;
43
44                 if (*in_pos >= in_size)
45                         return LZMA_BUF_ERROR;
46         }
47
48         do {
49                 // Read the next byte. Use a temporary variable so that we
50                 // can update *in_pos immediately.
51                 const uint8_t byte = in[*in_pos];
52                 ++*in_pos;
53
54                 // Add the newly read byte to *vli.
55                 *vli += (lzma_vli)(byte & 0x7F) << (*vli_pos * 7);
56                 ++*vli_pos;
57
58                 // Check if this is the last byte of a multibyte integer.
59                 if ((byte & 0x80) == 0) {
60                         // We don't allow using variable-length integers as
61                         // padding i.e. the encoding must use the most the
62                         // compact form.
63                         if (byte == 0x00 && *vli_pos > 1)
64                                 return LZMA_DATA_ERROR;
65
66                         return vli_pos == &vli_pos_internal
67                                         ? LZMA_OK : LZMA_STREAM_END;
68                 }
69
70                 // There is at least one more byte coming. If we have already
71                 // read maximum number of bytes, the integer is considered
72                 // corrupt.
73                 //
74                 // If we need bigger integers in future, old versions liblzma
75                 // will confusingly indicate the file being corrupt istead of
76                 // unsupported. I suppose it's still better this way, because
77                 // in the foreseeable future (writing this in 2008) the only
78                 // reason why files would appear having over 63-bit integers
79                 // is that the files are simply corrupt.
80                 if (*vli_pos == LZMA_VLI_BYTES_MAX)
81                         return LZMA_DATA_ERROR;
82
83         } while (*in_pos < in_size);
84
85         return vli_pos == &vli_pos_internal ? LZMA_DATA_ERROR : LZMA_OK;
86 }