aboutsummaryrefslogtreecommitdiffstats
path: root/lib/decompress_unlz4.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/decompress_unlz4.c')
-rw-r--r--lib/decompress_unlz4.c83
1 files changed, 52 insertions, 31 deletions
diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c
index 7d1e83caf8ad..40f66ebe57b7 100644
--- a/lib/decompress_unlz4.c
+++ b/lib/decompress_unlz4.c
@@ -31,10 +31,10 @@
31#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20) 31#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
32#define ARCHIVE_MAGICNUMBER 0x184C2102 32#define ARCHIVE_MAGICNUMBER 0x184C2102
33 33
34STATIC inline int INIT unlz4(u8 *input, int in_len, 34STATIC inline int INIT unlz4(u8 *input, long in_len,
35 int (*fill) (void *, unsigned int), 35 long (*fill)(void *, unsigned long),
36 int (*flush) (void *, unsigned int), 36 long (*flush)(void *, unsigned long),
37 u8 *output, int *posp, 37 u8 *output, long *posp,
38 void (*error) (char *x)) 38 void (*error) (char *x))
39{ 39{
40 int ret = -1; 40 int ret = -1;
@@ -43,7 +43,7 @@ STATIC inline int INIT unlz4(u8 *input, int in_len,
43 u8 *inp; 43 u8 *inp;
44 u8 *inp_start; 44 u8 *inp_start;
45 u8 *outp; 45 u8 *outp;
46 int size = in_len; 46 long size = in_len;
47#ifdef PREBOOT 47#ifdef PREBOOT
48 size_t out_len = get_unaligned_le32(input + in_len); 48 size_t out_len = get_unaligned_le32(input + in_len);
49#endif 49#endif
@@ -83,13 +83,20 @@ STATIC inline int INIT unlz4(u8 *input, int in_len,
83 if (posp) 83 if (posp)
84 *posp = 0; 84 *posp = 0;
85 85
86 if (fill) 86 if (fill) {
87 fill(inp, 4); 87 size = fill(inp, 4);
88 if (size < 4) {
89 error("data corrupted");
90 goto exit_2;
91 }
92 }
88 93
89 chunksize = get_unaligned_le32(inp); 94 chunksize = get_unaligned_le32(inp);
90 if (chunksize == ARCHIVE_MAGICNUMBER) { 95 if (chunksize == ARCHIVE_MAGICNUMBER) {
91 inp += 4; 96 if (!fill) {
92 size -= 4; 97 inp += 4;
98 size -= 4;
99 }
93 } else { 100 } else {
94 error("invalid header"); 101 error("invalid header");
95 goto exit_2; 102 goto exit_2;
@@ -100,29 +107,44 @@ STATIC inline int INIT unlz4(u8 *input, int in_len,
100 107
101 for (;;) { 108 for (;;) {
102 109
103 if (fill) 110 if (fill) {
104 fill(inp, 4); 111 size = fill(inp, 4);
112 if (size == 0)
113 break;
114 if (size < 4) {
115 error("data corrupted");
116 goto exit_2;
117 }
118 }
105 119
106 chunksize = get_unaligned_le32(inp); 120 chunksize = get_unaligned_le32(inp);
107 if (chunksize == ARCHIVE_MAGICNUMBER) { 121 if (chunksize == ARCHIVE_MAGICNUMBER) {
108 inp += 4; 122 if (!fill) {
109 size -= 4; 123 inp += 4;
124 size -= 4;
125 }
110 if (posp) 126 if (posp)
111 *posp += 4; 127 *posp += 4;
112 continue; 128 continue;
113 } 129 }
114 inp += 4; 130
115 size -= 4;
116 131
117 if (posp) 132 if (posp)
118 *posp += 4; 133 *posp += 4;
119 134
120 if (fill) { 135 if (!fill) {
136 inp += 4;
137 size -= 4;
138 } else {
121 if (chunksize > lz4_compressbound(uncomp_chunksize)) { 139 if (chunksize > lz4_compressbound(uncomp_chunksize)) {
122 error("chunk length is longer than allocated"); 140 error("chunk length is longer than allocated");
123 goto exit_2; 141 goto exit_2;
124 } 142 }
125 fill(inp, chunksize); 143 size = fill(inp, chunksize);
144 if (size < chunksize) {
145 error("data corrupted");
146 goto exit_2;
147 }
126 } 148 }
127#ifdef PREBOOT 149#ifdef PREBOOT
128 if (out_len >= uncomp_chunksize) { 150 if (out_len >= uncomp_chunksize) {
@@ -149,18 +171,17 @@ STATIC inline int INIT unlz4(u8 *input, int in_len,
149 if (posp) 171 if (posp)
150 *posp += chunksize; 172 *posp += chunksize;
151 173
152 size -= chunksize; 174 if (!fill) {
175 size -= chunksize;
153 176
154 if (size == 0) 177 if (size == 0)
155 break; 178 break;
156 else if (size < 0) { 179 else if (size < 0) {
157 error("data corrupted"); 180 error("data corrupted");
158 goto exit_2; 181 goto exit_2;
182 }
183 inp += chunksize;
159 } 184 }
160
161 inp += chunksize;
162 if (fill)
163 inp = inp_start;
164 } 185 }
165 186
166 ret = 0; 187 ret = 0;
@@ -175,11 +196,11 @@ exit_0:
175} 196}
176 197
177#ifdef PREBOOT 198#ifdef PREBOOT
178STATIC int INIT decompress(unsigned char *buf, int in_len, 199STATIC int INIT decompress(unsigned char *buf, long in_len,
179 int(*fill)(void*, unsigned int), 200 long (*fill)(void*, unsigned long),
180 int(*flush)(void*, unsigned int), 201 long (*flush)(void*, unsigned long),
181 unsigned char *output, 202 unsigned char *output,
182 int *posp, 203 long *posp,
183 void(*error)(char *x) 204 void(*error)(char *x)
184 ) 205 )
185{ 206{