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 return -1; // Unexpected end of src
27 s = *src++;
28 lit_len += s;
29 } while (s == 255);
30 }
31
32 if (lit_len > 0) {
33 if ((size_t)(src_end - src) < lit_len ||
34 (size_t)(dst_end - dst_ptr) < lit_len) {
35 return -1;
36 }
37
38 unsigned int l = lit_len;
39 do {
40 *dst_ptr++ = *src++;
41 } while (--l);
42 }
43
44 if (src >= src_end) {
45 break;
46 }
47
48 // Process match offset
49 if (src + 2 > src_end)
50 return -1;
51 uint16_t offset = (uint16_t)(src[0] | (src[1] << 8));
52 src += 2;
53
54 if (offset == 0 || offset > (size_t)(dst_ptr - dst)) {
55 return -1; // Offset out of bounds
56 }
57
58 unsigned int match_len = token & 0x0F;
59 if (match_len == 15) {
60 uint8_t s;
61 do {
62 if (src >= src_end)
63 return -1;
64 s = *src++;
65 match_len += s;
66 } while (s == 255);
67 }
68 match_len += 4;
69
70 // Check bounds for match destination
71 if ((size_t)(dst_end - dst_ptr) < match_len) {
72 return -1;
73 }
74
75 const uint8_t *match_ptr = dst_ptr - offset;
76 unsigned int m = match_len;
77 do {
78 *dst_ptr++ = *match_ptr++;
79 } while (--m);
80 }
81
82 return (int)(dst_ptr - dst);
83}