clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name decompress.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -pic-is-pie -mthread-model posix -mframe-pointer=all -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -resource-dir /usr/lib/clang/10.0.0 -I ./src -I ./src/inc -internal-isystem /usr/local/include -internal-isystem /usr/lib/clang/10.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-sign-compare -std=c11 -fdebug-compilation-dir /tmp/ssgctv09 -ferror-limit 19 -fmessage-length 0 -stack-protector 2 -fobjc-runtime=gcc -fdiagnostics-show-option -analyzer-checker alpha.core.CallAndMessageUnInitRefArg -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.Conversion -analyzer-checker alpha.core.FixedAddr -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.PointerArithm -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.core.TestAfterDivZero -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.BlockInCriticalSection -analyzer-checker alpha.unix.Chroot -analyzer-checker alpha.unix.PthreadLock -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.Stream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker valist.CopyToSelf -analyzer-checker valist.Uninitialized -analyzer-checker valist.Unterminated -analyzer-checker security.FloatLoopCounter -analyzer-checker security.insecureAPI.strcpy -analyzer-max-loop 1536 -analyzer-output=html -faddrsig -o /tmp/scan-build-2019-10-07-120410-3045-1 -x c src/decompress.c
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | #include <stdio.h>
|
25 | #include <stdlib.h>
|
26 | #include <stdint.h>
|
27 | #include <string.h>
|
28 | #include <byteswap.h>
|
29 |
|
30 | #include "compression.h"
|
31 |
|
32 | const uint8_t lut_seed[9] = {0, 128, 64, 32, 16, 8, 4, 2, 1};
|
33 | static uint16_t decomp_lut[256];
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | static uint16_t extract_lut_data(uint16_t* p_offset_code, uint8_t** pp_lut_data)
|
42 | {
|
43 | uint16_t shift_code = *p_offset_code >> 4;
|
44 | uint32_t fetched_source_data;
|
45 |
|
46 | if (shift_code > 31){
|
47 | *pp_lut_data += 4;
|
48 | shift_code -= 32;
|
49 | *p_offset_code = shift_code << 4;
|
50 | }
|
51 |
|
52 | uint8_t* p_source_data = *pp_lut_data;
|
53 |
|
54 | if (shift_code < 25){
|
55 | fetched_source_data = __bswap_32(*((uint32_t*) p_source_data)) >> (24 - shift_code);
|
56 | } else {
|
57 | fetched_source_data = __bswap_32(*((uint32_t*) p_source_data)) << (shift_code - 24);
|
58 | fetched_source_data |= __bswap_32(*((uint32_t*) (p_source_data + 4))) >> (56 - shift_code);
|
59 | }
|
60 |
|
61 | return (uint16_t) ((fetched_source_data & 0xff) << 1);
|
62 | }
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | static uint8_t generate_lut(uint8_t* p_comp_lut)
|
70 | {
|
71 | uint8_t rtn = 0;
|
72 | uint8_t bit_num;
|
73 | uint8_t max_bit_num;
|
74 | uint8_t decode_char;
|
75 | uint16_t lut_elem;
|
76 | uint16_t *p_decomp_lut = &decomp_lut[0];
|
77 |
|
78 | for(uint_fast8_t j = 0; j < 17; j++){
|
79 | max_bit_num = 0;
|
80 | for(uint_fast8_t i = 0; i < 17; i++){
|
81 | if (i%2){
|
82 | bit_num = *(p_comp_lut + (i/2)) & 0xf;
|
83 | } else {
|
84 | bit_num = *(p_comp_lut + (i/2)) >> 4;
|
85 | }
|
86 |
|
87 | if (bit_num > max_bit_num){
|
88 | max_bit_num = bit_num;
|
89 | decode_char = i;
|
90 | }
|
91 | }
|
92 |
|
93 | if (max_bit_num > 8){
|
94 | rtn = 1;
|
95 | break;
|
96 | } else if (max_bit_num == 0){
|
97 | break;
|
98 | }
|
99 |
|
100 | if (decode_char%2){
|
101 | *(p_comp_lut + (decode_char/2)) &= 0xf0;
|
102 | } else {
|
103 | *(p_comp_lut + (decode_char/2)) &= 0xf;
|
104 | }
|
105 |
|
106 | lut_elem = decode_char << 8;
|
107 | lut_elem |= max_bit_num << 4;
|
108 | if (decode_char == 16){
|
109 | lut_elem++;
|
110 | }
|
111 | for (uint_fast8_t i = 0; i < lut_seed[max_bit_num]; i++){
|
112 |
|
113 | *p_decomp_lut = lut_elem;
|
114 | p_decomp_lut++;
|
115 | }
|
116 | }
|
117 |
|
118 |
|
119 | if (p_decomp_lut != &decomp_lut[0] + 256){
|
120 | rtn = 1;
|
121 | }
|
122 | return rtn;
|
123 |
|
124 | }
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 | compression_status_t decompress(
|
137 | const char* input,
|
138 | const char* output,
|
139 | uint32_t comp_data_offset,
|
140 | enum comp_mode* p_mode,
|
141 | uint8_t* p_lut,
|
142 | uint8_t* p_rle_limit)
|
143 | {
|
144 | uint8_t* p_iso;
|
145 |
|
146 |
|
147 |
|
148 | int size = 0;
|
149 | FILE *f = fopen(input, "rb");
|
150 |
|
151 | if (f == NULL){
|
| |
152 | return FILE_NOT_FOUND;
|
153 | }
|
154 |
|
155 | fseek(f, 0, SEEK_END);
|
156 | size = ftell(f);
|
157 | fseek(f, 0, SEEK_SET);
|
158 |
|
159 | p_iso = (uint8_t *) malloc(size+1);
|
160 |
|
161 | if (size != fread(p_iso, sizeof(int8_t), size, f))
|
| 2 | | Assuming the condition is true | |
|
| |
162 | {
|
163 | free(p_iso);
|
| 4 | | Opened File never closed. Potential Resource leak |
|
164 | return INSUFFICIENT_MEM;
|
165 | }
|
166 | fclose(f);
|
167 |
|
168 |
|
169 | uint8_t* p_rle_data = p_iso + comp_data_offset;
|
170 | uint16_t head_data;
|
171 | head_data = __bswap_16(*((uint16_t*) p_rle_data));
|
172 | if ( (head_data >> 8) & 0x20){
|
173 | free(p_iso);
|
174 | return INVALID_HEADER;
|
175 | }
|
176 |
|
177 |
|
178 | uint8_t mode_bits = head_data >> 14;
|
179 | enum comp_mode mode;
|
180 | switch (mode_bits){
|
181 | case 0b10:
|
182 | mode = SUB_MODE;
|
183 | break;
|
184 | case 0b00:
|
185 | mode = MOV_MODE;
|
186 | break;
|
187 | case 0b01:
|
188 | mode = XOR_MODE;
|
189 | break;
|
190 | default:
|
191 | free(p_iso);
|
192 | return INVALID_HEADER;
|
193 | }
|
194 | *p_mode = mode;
|
195 |
|
196 |
|
197 | uint16_t table_offset = head_data;
|
198 | table_offset = table_offset & 0x1fff;
|
199 | uint8_t* p_table_data = p_rle_data + table_offset + 2;
|
200 | memcpy(p_lut, p_table_data, 9);
|
201 | if (generate_lut(p_table_data)){
|
202 | free(p_iso);
|
203 | return INVALID_TABLE;
|
204 | }
|
205 |
|
206 |
|
207 | uint8_t* p_decompressed = (uint8_t*) calloc(64000, sizeof(uint8_t));
|
208 | uint8_t* p_output = p_decompressed;
|
209 |
|
210 |
|
211 | uint8_t* p_lut_data = p_rle_data + table_offset + 0xb;
|
212 | p_lut_data = (uint8_t*) (((uint32_t) p_lut_data) & 0xfffffffc);
|
213 |
|
214 |
|
215 | p_rle_data += 2;
|
216 |
|
217 |
|
218 | uint8_t rle_zeros_cntr = 0;
|
219 | uint8_t rle_limit = 0;
|
220 | uint16_t zero_num = 0;
|
221 | uint16_t zero_diff;
|
222 | uint32_t decoded_bits_num = 0;
|
223 |
|
224 | uint16_t shift_code = ((table_offset + 0xb) & 0x3) << 7;
|
225 | uint16_t decompressed_bits = 0;
|
226 | uint8_t rle_prefix;
|
227 | uint32_t lut_index = 0;
|
228 | uint16_t lut_data;
|
229 | uint_fast8_t is_aligned = 0;
|
230 |
|
231 | uint_fast32_t run_cntr = 0;
|
232 | while(1){
|
233 |
|
234 | run_cntr++;
|
235 |
|
236 | if (run_cntr > MAX_DECOMP_LEN){
|
237 | free(p_decompressed);
|
238 | free(p_iso);
|
239 | return RUNAWAY_DATA;
|
240 | }
|
241 |
|
242 |
|
243 | if (is_aligned){
|
244 | rle_prefix = *p_rle_data & 0xf;
|
245 | p_rle_data++;
|
246 | is_aligned = 0;
|
247 | } else {
|
248 | rle_prefix = *p_rle_data >> 4;
|
249 | is_aligned = 1;
|
250 | }
|
251 |
|
252 |
|
253 | switch (rle_prefix){
|
254 | case 0xD:
|
255 | if (is_aligned){
|
256 | zero_diff = *p_rle_data & 0xf;
|
257 | is_aligned = 0;
|
258 | p_rle_data++;
|
259 | } else {
|
260 | zero_diff = *p_rle_data >> 4;
|
261 | is_aligned = 1;
|
262 | }
|
263 | if (zero_diff >= 8){
|
264 | zero_num += (zero_diff - 1);
|
265 | } else {
|
266 | zero_num += zero_diff - 14;
|
267 | }
|
268 | break;
|
269 |
|
270 | case 0xE:
|
271 | if (is_aligned){
|
272 | zero_num = (*p_rle_data & 0xf) << 4;
|
273 | p_rle_data++;
|
274 | zero_num |= *p_rle_data >> 4;
|
275 | } else {
|
276 | zero_num = *p_rle_data;
|
277 | p_rle_data++;
|
278 | }
|
279 | break;
|
280 |
|
281 | case 0xF:
|
282 | if (is_aligned){
|
283 | zero_num = (*p_rle_data & 0xf) << 12;
|
284 | p_rle_data++;
|
285 | zero_num |= *p_rle_data << 4;
|
286 | p_rle_data++;
|
287 | zero_num |= (*p_rle_data & 0xf0) >> 4;
|
288 | } else {
|
289 | zero_num = *p_rle_data << 8;
|
290 | p_rle_data++;
|
291 | zero_num |= *p_rle_data;
|
292 | p_rle_data++;
|
293 | }
|
294 | break;
|
295 |
|
296 | default:
|
297 | zero_num += rle_prefix - 6;
|
298 | break;
|
299 | }
|
300 |
|
301 |
|
302 |
|
303 | if (zero_num){
|
304 |
|
305 | if (decoded_bits_num % 2){
|
306 | p_output += (zero_num - 1) / 2;
|
307 | } else {
|
308 | p_output += zero_num / 2;
|
309 | }
|
310 | decoded_bits_num += zero_num;
|
311 |
|
312 | } else {
|
313 | break;
|
314 | }
|
315 |
|
316 | while (1){
|
317 |
|
318 |
|
319 | lut_index = extract_lut_data(&shift_code, &p_lut_data);
|
320 | lut_data = decomp_lut[lut_index/2];
|
321 |
|
322 |
|
323 | if (!(lut_data & 0x1)){
|
324 | shift_code += lut_data & 0xff;
|
325 | lut_data >>= 8;
|
326 | switch (mode){
|
327 | case SUB_MODE:
|
328 | decompressed_bits = (decompressed_bits - lut_data) & 0xf;
|
329 | break;
|
330 | case MOV_MODE:
|
331 | decompressed_bits = lut_data & 0xf;
|
332 | break;
|
333 | case XOR_MODE:
|
334 | decompressed_bits = (decompressed_bits ^ lut_data) & 0xf;
|
335 | break;
|
336 | }
|
337 |
|
338 | if (decompressed_bits == 0){
|
339 | rle_zeros_cntr++;
|
340 | } else {
|
341 | if (rle_limit < rle_zeros_cntr){
|
342 | rle_limit = rle_zeros_cntr;
|
343 | }
|
344 | rle_zeros_cntr = 0;
|
345 | }
|
346 |
|
347 | if (decoded_bits_num % 2){
|
348 | *p_output |= decompressed_bits;
|
349 | p_output++;
|
350 | decoded_bits_num++;
|
351 | } else {
|
352 | *p_output = decompressed_bits << 4;
|
353 | decoded_bits_num++;
|
354 | }
|
355 |
|
356 | } else {
|
357 | if (decoded_bits_num % 2){
|
358 | p_output++;
|
359 | }
|
360 | shift_code += lut_data & 0xf0;
|
361 | break;
|
362 | }
|
363 | }
|
364 | }
|
365 |
|
366 | f = fopen(output, "wb");
|
367 | fwrite(p_decompressed, sizeof(uint8_t), (int32_t) (p_output - p_decompressed), f);
|
368 | fclose(f);
|
369 |
|
370 | free(p_decompressed);
|
371 | free(p_iso);
|
372 |
|
373 | *p_rle_limit = rle_limit + 1;
|
374 |
|
375 | return SUCCESS;
|
376 | }
|