Software APIs
lz4.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "sw/device/lib/base/lz4.h"
6
7#include <stdint.h>
8
9int LZ4_decompress(const char *src_in, char *dst_in, int compressed_size,
10 int dst_capacity) {
11 const uint8_t *src = (const uint8_t *)src_in;
12 const uint8_t *src_end = src + compressed_size;
13 uint8_t *dst = (uint8_t *)dst_in;
14 uint8_t *dst_end = dst + dst_capacity;
15 uint8_t *dst_ptr = dst;
16
17 while (src < src_end) {
18 uint8_t token = *src++;
19
20 // Process literals
21 unsigned int lit_len = token >> 4;
22 if (lit_len == 15) {
23 uint8_t s;
24 do {
25 if (src >= src_end) {
26 // COVERAGE (SW ERR) Decompression is only called on valid build-time
27 // compressed data.
28 return -1; // Unexpected end of src
29 }
30 s = *src++;
31 lit_len += s;
32 } while (s == 255);
33 }
34
35 if (lit_len > 0) {
36 if ((size_t)(src_end - src) < lit_len ||
37 (size_t)(dst_end - dst_ptr) < lit_len) {
38 // COVERAGE (SW ERR) Decompression is only called on valid build-time
39 // compressed data.
40 return -1;
41 }
42
43 unsigned int l = lit_len;
44 do {
45 *dst_ptr++ = *src++;
46 } while (--l);
47 }
48
49 if (src >= src_end) {
50 break;
51 }
52
53 // Process match offset
54 if (src + 2 > src_end) {
55 // COVERAGE (SW ERR) Decompression is only called on valid build-time
56 // compressed data.
57 return -1;
58 }
59 uint16_t offset = (uint16_t)(src[0] | (src[1] << 8));
60 src += 2;
61
62 if (offset == 0 || offset > (size_t)(dst_ptr - dst)) {
63 // COVERAGE (SW ERR) Decompression is only called on valid build-time
64 // compressed data.
65 return -1; // Offset out of bounds
66 }
67
68 unsigned int match_len = token & 0x0F;
69 if (match_len == 15) {
70 uint8_t s;
71 do {
72 if (src >= src_end) {
73 // COVERAGE (SW ERR) Decompression is only called on valid build-time
74 // compressed data.
75 return -1;
76 }
77 s = *src++;
78 match_len += s;
79 } while (s == 255);
80 }
81 match_len += 4;
82
83 // Check bounds for match destination
84 if ((size_t)(dst_end - dst_ptr) < match_len) {
85 // COVERAGE (SW ERR) Decompression is only called on valid build-time
86 // compressed data.
87 return -1;
88 }
89
90 const uint8_t *match_ptr = dst_ptr - offset;
91 unsigned int m = match_len;
92 do {
93 *dst_ptr++ = *match_ptr++;
94 } while (--m);
95 }
96
97 return (int)(dst_ptr - dst);
98}