xref: /freebsd/contrib/xz/src/liblzma/common/vli_decoder.c (revision 8d20be1e22095c27faf8fe8b2f0d089739cc742e)
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 }
87