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