diff options
Diffstat (limited to 'lib/decompress_unlz4.c')
-rw-r--r-- | lib/decompress_unlz4.c | 83 |
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 | ||
34 | STATIC inline int INIT unlz4(u8 *input, int in_len, | 34 | STATIC 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 |
178 | STATIC int INIT decompress(unsigned char *buf, int in_len, | 199 | STATIC 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 | { |