clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name compress.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/compress.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 | #include "compression.h"
|
30 |
|
31 | static uint8_t compr_lut_shifts[16];
|
32 | static uint8_t compr_lut_offset[16];
|
33 | static uint8_t compr_shifts_stop;
|
34 | static uint8_t compr_offset_stop;
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | static uint8_t generate_lut(uint8_t* p_comp_lut)
|
42 | {
|
43 | uint8_t rtn = 0;
|
44 | uint8_t bit_num;
|
45 | uint8_t max_bit_num;
|
46 | uint8_t decode_char;
|
47 | uint16_t offset = 0;
|
48 |
|
49 | for(uint_fast8_t j = 0; j < 17; j++){
|
50 | max_bit_num = 0;
|
51 | for(uint_fast8_t i = 0; i < 17; i++){
|
52 | if (i%2){
|
53 | bit_num = *(p_comp_lut + (i/2)) & 0xf;
|
54 | } else {
|
55 | bit_num = *(p_comp_lut + (i/2)) >> 4;
|
56 | }
|
57 |
|
58 | if (bit_num > max_bit_num){
|
59 | max_bit_num = bit_num;
|
60 | decode_char = i;
|
61 | }
|
62 | }
|
63 |
|
64 | if (max_bit_num > 8){
|
65 | rtn = 1;
|
66 | break;
|
67 | } else if (max_bit_num == 0){
|
68 | rtn = 0;
|
69 | break;
|
70 | }
|
71 |
|
72 | if (decode_char%2){
|
73 | *(p_comp_lut + (decode_char/2)) &= 0xf0;
|
74 | } else {
|
75 | *(p_comp_lut + (decode_char/2)) &= 0xf;
|
76 | }
|
77 |
|
78 | if (decode_char == 16){
|
79 | compr_offset_stop = offset;
|
80 | compr_shifts_stop = max_bit_num;
|
81 | } else {
|
82 | compr_lut_offset[decode_char] = offset;
|
83 | compr_lut_shifts[decode_char] = max_bit_num;
|
84 | }
|
85 | offset += lut_seed[max_bit_num];
|
86 | }
|
87 |
|
88 |
|
89 | if (offset != 256){
|
90 | rtn = 1;
|
91 | }
|
92 | return rtn;
|
93 |
|
94 | }
|
95 |
|
96 |
|
97 | uint8_t* p_input_data;
|
98 | uint_fast8_t input_bit_pos = 0;
|
99 |
|
100 |
|
101 | uint8_t* p_rle_data;
|
102 | uint_fast8_t rle_bit_pos = 1;
|
103 |
|
104 |
|
105 | uint8_t* p_delta_data;
|
106 | uint_fast8_t delta_bit_pos = 0;
|
107 |
|
108 | uint8_t* p_end_of_file;
|
109 | uint8_t end_of_file = 0;
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | static inline void store_input_pos(uint8_t restore_flag)
|
117 | {
|
118 | static uint8_t* last_p_input_data;
|
119 | static uint_fast8_t last_input_bit_pos;
|
120 |
|
121 | if (restore_flag){
|
122 | p_input_data = last_p_input_data;
|
123 | input_bit_pos = last_input_bit_pos;
|
124 | } else {
|
125 | last_p_input_data = p_input_data;
|
126 | last_input_bit_pos = input_bit_pos;
|
127 | }
|
128 | }
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 | static uint8_t get_next_input_bits(void)
|
135 | {
|
136 | uint8_t rtn;
|
137 |
|
138 | if (p_input_data > p_end_of_file){
|
139 | end_of_file = 1;
|
140 | return 0;
|
141 | }
|
142 |
|
143 | rtn = (*p_input_data >> (4 - input_bit_pos)) & 0xf;
|
144 | input_bit_pos += 4;
|
145 | if (input_bit_pos > 4){
|
146 | input_bit_pos = 0;
|
147 | p_input_data++;
|
148 | }
|
149 | return rtn;
|
150 | }
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | static uint8_t test_next_bits(uint_fast16_t* p_num_bits, uint8_t rle_limit)
|
159 | {
|
160 | *p_num_bits = 0;
|
161 |
|
162 | uint8_t ref;
|
163 | uint8_t test_bits;
|
164 | uint8_t* _p_input_data;
|
165 | uint_fast8_t _input_bit_pos;
|
166 | uint8_t zero_cntr;
|
167 |
|
168 | ref = get_next_input_bits() == 0;
|
169 | do {
|
170 | _p_input_data = p_input_data;
|
171 | _input_bit_pos = input_bit_pos;
|
172 | test_bits = get_next_input_bits() == 0;
|
173 | (*p_num_bits)++;
|
174 |
|
175 |
|
176 | zero_cntr = rle_limit - 1;
|
177 | while ((!ref && test_bits) && zero_cntr--){
|
178 | test_bits = get_next_input_bits() == 0;
|
179 | (*p_num_bits)++;
|
180 | }
|
181 |
|
182 | } while ( ref == test_bits && !end_of_file);
|
183 |
|
184 | zero_cntr++;
|
185 | if (!zero_cntr){
|
186 | *p_num_bits -= rle_limit - 1;
|
187 | }
|
188 |
|
189 | if (ref){
|
190 | p_input_data = _p_input_data;
|
191 | input_bit_pos = _input_bit_pos;
|
192 | }
|
193 |
|
194 | return ref;
|
195 | }
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 | static void encode_zeros(uint16_t num_zeros)
|
203 | {
|
204 | static uint16_t prev_num_zeros = 0;
|
205 |
|
206 | uint32_t new_data;
|
207 | uint_fast8_t new_data_len;
|
208 |
|
209 | uint16_t zero_blocks = num_zeros / 8;
|
210 | uint8_t zeros = num_zeros % 8;
|
211 |
|
212 | if ( (num_zeros - prev_num_zeros) > -7 && (num_zeros - prev_num_zeros) < 7){
|
213 | new_data = (num_zeros - prev_num_zeros) + 6;
|
214 | new_data_len = 1;
|
215 | } else if ( (num_zeros - prev_num_zeros) > -15 && (num_zeros - prev_num_zeros) < 15){
|
216 | new_data = 0xd << 4;
|
217 | if ((num_zeros - prev_num_zeros) >= 7 ){
|
218 | new_data |= (num_zeros - prev_num_zeros) + 1;
|
219 | } else {
|
220 | new_data |= (num_zeros - prev_num_zeros) + 14;
|
221 | }
|
222 | new_data_len = 2;
|
223 | } else if (zero_blocks < 32){
|
224 | new_data = 0xe << 8;
|
225 | new_data |= zero_blocks << 3 | zeros;
|
226 | new_data_len = 3;
|
227 | } else {
|
228 | new_data = 0xf << 16;
|
229 | new_data |= zero_blocks << 3 | zeros;
|
230 | new_data_len = 5;
|
231 | }
|
232 |
|
233 | uint8_t next_bits;
|
234 | while(new_data_len--){
|
235 | next_bits = (new_data >> (new_data_len * 4)) & 0xf;
|
236 | *p_rle_data |= next_bits << ((rle_bit_pos % 2) * 4);
|
237 | if (!(rle_bit_pos % 2)){
|
238 | p_rle_data++;
|
239 | *p_rle_data = 0;
|
240 | }
|
241 | rle_bit_pos++;
|
242 | }
|
243 |
|
244 | prev_num_zeros = num_zeros;
|
245 | }
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 | static void encode_data(enum comp_mode mode, uint16_t num_bits)
|
254 | {
|
255 | static uint8_t val = 0;
|
256 | uint8_t next_val;
|
257 | uint8_t diff;
|
258 | uint8_t shifts;
|
259 |
|
260 | while(num_bits--){
|
261 | next_val = get_next_input_bits();
|
262 | switch (mode){
|
263 | case SUB_MODE:
|
264 | diff = (val - next_val) & 0xf;
|
265 | break;
|
266 | case MOV_MODE:
|
267 | diff = next_val & 0xf;
|
268 | break;
|
269 | case XOR_MODE:
|
270 | diff = (val ^ next_val) & 0xf;
|
271 | break;
|
272 | }
|
273 | shifts = compr_lut_shifts[diff];
|
274 | val = next_val;
|
275 |
|
276 |
|
277 | if (delta_bit_pos == 0){
|
278 | *p_delta_data = compr_lut_offset[diff];
|
279 | } else {
|
280 | *p_delta_data |= compr_lut_offset[diff] >> delta_bit_pos;
|
281 | *(p_delta_data + 1) |= compr_lut_offset[diff] << ( 8 - delta_bit_pos);
|
282 | }
|
283 |
|
284 |
|
285 | delta_bit_pos += shifts;
|
286 | if (delta_bit_pos >= 8){
|
287 | delta_bit_pos -= 8;
|
288 | p_delta_data++;
|
289 | }
|
290 | }
|
291 |
|
292 | if (delta_bit_pos == 0){
|
293 | *p_delta_data = compr_offset_stop;
|
294 | } else {
|
295 | *p_delta_data |= compr_offset_stop >> delta_bit_pos;
|
296 | *(p_delta_data + 1) |= compr_offset_stop << ( 8 - delta_bit_pos);
|
297 | }
|
298 |
|
299 | delta_bit_pos += compr_shifts_stop;
|
300 | if (delta_bit_pos >= 8){
|
301 | delta_bit_pos -= 8;
|
302 | p_delta_data++;
|
303 | }
|
304 |
|
305 | }
|
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 |
|
312 |
|
313 |
|
314 |
|
315 |
|
316 | compression_status_t compress(
|
317 | enum comp_mode mode,
|
318 | const char* input,
|
319 | const char* output,
|
320 | uint8_t* p_table,
|
321 | uint8_t rle_limit)
|
322 | {
|
323 | int size = 0;
|
324 | int rsize = 0;
|
325 | FILE *f = fopen(input, "rb");
|
326 |
|
327 | uint8_t table[9];
|
328 | memcpy(table, p_table, 9);
|
329 |
|
330 | if (f == NULL){
|
| |
331 | return FILE_NOT_FOUND;
|
332 | }
|
333 |
|
334 | fseek(f, 0, SEEK_END);
|
335 | size = ftell(f);
|
336 | fseek(f, 0, SEEK_SET);
|
337 |
|
338 | p_input_data = (uint8_t *) malloc(size);
|
339 | p_end_of_file = p_input_data + size -1;
|
340 | rsize = fread(p_input_data, sizeof(uint8_t), size, f);
|
341 |
|
342 | if (size != rsize)
|
| 2 | | Assuming 'size' is not equal to 'rsize' | |
|
| |
343 | {
|
344 | free(p_input_data);
|
| 4 | | Opened File never closed. Potential Resource leak |
|
345 | return INSUFFICIENT_MEM;
|
346 | }
|
347 | fclose(f);
|
348 |
|
349 |
|
350 |
|
351 | uint8_t* p_delta_data_start;
|
352 | uint8_t* p_rle_data_start;
|
353 | p_delta_data_start = (uint8_t *) calloc(32000, sizeof(uint8_t*));
|
354 | p_rle_data_start = (uint8_t *) malloc(16000);
|
355 | p_delta_data = p_delta_data_start;
|
356 | p_rle_data = p_rle_data_start;
|
357 |
|
358 |
|
359 | if (generate_lut(p_table)){
|
360 | free(p_delta_data_start);
|
361 | free(p_rle_data_start);
|
362 | free(p_input_data);
|
363 | return INVALID_TABLE;
|
364 | }
|
365 |
|
366 | uint_fast16_t bit_cntr = 0;
|
367 | uint8_t is_zeros;
|
368 | *p_rle_data = 0;
|
369 | uint_fast32_t run_cntr = 0;
|
370 | while(!end_of_file){
|
371 |
|
372 | run_cntr++;
|
373 | if (run_cntr > MAX_COMP_LEN){
|
374 | free(p_delta_data_start);
|
375 | free(p_rle_data_start);
|
376 | free(p_input_data);
|
377 | return RUNAWAY_DATA;
|
378 | }
|
379 |
|
380 | store_input_pos(0);
|
381 | is_zeros = test_next_bits(&bit_cntr, rle_limit);
|
382 |
|
383 | if (is_zeros){
|
384 | encode_zeros(bit_cntr);
|
385 | } else {
|
386 | store_input_pos(1);
|
387 | encode_data(mode, bit_cntr);
|
388 | }
|
389 | }
|
390 |
|
391 |
|
392 | uint32_t new_data = 0xe00;
|
393 | uint8_t new_data_len = 3;
|
394 | uint8_t next_bits;
|
395 | while(new_data_len--){
|
396 | next_bits = (new_data >> (new_data_len * 4)) & 0xf;
|
397 | *p_rle_data |= next_bits << ((rle_bit_pos % 2) * 4);
|
398 | if (!(rle_bit_pos % 2)){
|
399 | p_rle_data++;
|
400 | *p_rle_data = 0;
|
401 | }
|
402 | rle_bit_pos++;
|
403 | }
|
404 | if (!(rle_bit_pos % 2)){
|
405 | p_rle_data++;
|
406 | }
|
407 |
|
408 |
|
409 | if (is_zeros){
|
410 | if (delta_bit_pos == 0){
|
411 | *p_delta_data = compr_offset_stop;
|
412 | } else {
|
413 | *p_delta_data |= compr_offset_stop >> delta_bit_pos;
|
414 | *(p_delta_data + 1) |= compr_offset_stop << ( 8 - delta_bit_pos);
|
415 | }
|
416 |
|
417 | delta_bit_pos += compr_shifts_stop;
|
418 | if (delta_bit_pos >= 8){
|
419 | delta_bit_pos -= 8;
|
420 | p_delta_data++;
|
421 | }
|
422 | }
|
423 |
|
424 |
|
425 | if (delta_bit_pos != 0){
|
426 | p_delta_data++;
|
427 | }
|
428 |
|
429 |
|
430 | uint16_t head;
|
431 | switch (mode){
|
432 | case SUB_MODE:
|
433 | head = 0b10 << 14;
|
434 | break;
|
435 | case MOV_MODE:
|
436 | head = 0b00 << 14;
|
437 | break;
|
438 | case XOR_MODE:
|
439 | head = 0b01 << 14;
|
440 | break;
|
441 | }
|
442 | head |= (uint16_t) (p_rle_data - p_rle_data_start);
|
443 | head = __bswap_16(head);
|
444 |
|
445 | f = fopen(output, "wb");
|
446 | fwrite(&head, sizeof(int16_t), 1, f);
|
447 | fwrite(p_rle_data_start, sizeof(int8_t), (int32_t) (p_rle_data - p_rle_data_start), f);
|
448 | fwrite(table, sizeof(int8_t), 9, f);
|
449 | fwrite(p_delta_data_start, sizeof(int8_t), (int32_t) (p_delta_data - p_delta_data_start), f);
|
450 | fclose(f);
|
451 |
|
452 | free(p_delta_data_start);
|
453 | free(p_rle_data_start);
|
454 | free(p_input_data);
|
455 |
|
456 | return SUCCESS;
|
457 | }
|