more consistent types, some bounds checking
This commit is contained in:
parent
d8e6310bb5
commit
fb163a5b08
4 changed files with 70 additions and 28 deletions
36
compress.c
36
compress.c
|
@ -52,8 +52,10 @@ uint16_t offsets[256][256];
|
|||
// Compresses a file of up to 64 kb.
|
||||
// unpacked/packed are 65536 byte buffers to read/from write to,
|
||||
// inputsize is the length of the uncompressed data.
|
||||
// Returns the size of the compressed data in bytes.
|
||||
size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
||||
// Returns the size of the compressed data in bytes, or 0 if compression failed.
|
||||
size_t pack(uint8_t *unpacked, size_t inputsize, uint8_t *packed, int fast) {
|
||||
if (inputsize > DATA_SIZE) return 0;
|
||||
|
||||
// current input/output positions
|
||||
uint32_t inpos = 0;
|
||||
uint32_t outpos = 0;
|
||||
|
@ -87,6 +89,9 @@ size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
|||
|
||||
// if the backref is a better candidate, use it
|
||||
if (backref.size > 3 && backref.size > rle.size) {
|
||||
if (outpos + dontpacksize + backref.size >= DATA_SIZE)
|
||||
return 0;
|
||||
|
||||
// flush the raw data buffer first
|
||||
outpos += write_raw(packed, outpos, dontpack, dontpacksize);
|
||||
dontpacksize = 0;
|
||||
|
@ -96,8 +101,10 @@ size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
|||
}
|
||||
// or if the RLE is a better candidate, use it instead
|
||||
else if (rle.size >= 2) {
|
||||
if (outpos + dontpacksize + rle.size >= DATA_SIZE)
|
||||
return 0;
|
||||
|
||||
// flush the raw data buffer first
|
||||
|
||||
outpos += write_raw(packed, outpos, dontpack, dontpacksize);
|
||||
dontpacksize = 0;
|
||||
|
||||
|
@ -109,6 +116,9 @@ size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
|||
else {
|
||||
dontpack[dontpacksize++] = unpacked[inpos++];
|
||||
|
||||
if (outpos + dontpacksize >= DATA_SIZE)
|
||||
return 0;
|
||||
|
||||
// if the raw data buffer is full, flush it
|
||||
if (dontpacksize == LONG_RUN_SIZE) {
|
||||
outpos += write_raw(packed, outpos, dontpack, dontpacksize);
|
||||
|
@ -118,6 +128,9 @@ size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
|||
}
|
||||
|
||||
// flush any remaining uncompressed data
|
||||
if (outpos + dontpacksize + 1 > DATA_SIZE)
|
||||
return 0;
|
||||
|
||||
outpos += write_raw(packed, outpos, dontpack, dontpacksize);
|
||||
|
||||
//add the terminating byte
|
||||
|
@ -128,7 +141,7 @@ size_t pack(uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast) {
|
|||
|
||||
// Decompresses a file of up to 64 kb.
|
||||
// unpacked/packed are 65536 byte buffers to read/from write to,
|
||||
// Returns the size of the uncompressed data in bytes.
|
||||
// Returns the size of the uncompressed data in bytes or 0 if decompression failed.
|
||||
size_t unpack(uint8_t *packed, uint8_t *unpacked) {
|
||||
// current input/output positions
|
||||
uint32_t inpos = 0;
|
||||
|
@ -156,6 +169,12 @@ size_t unpack(uint8_t *packed, uint8_t *unpacked) {
|
|||
length = (input & 0x1F) + 1;
|
||||
}
|
||||
|
||||
// don't try to decompress > 64kb
|
||||
if (((command == 2) && (outpos + 2*length > DATA_SIZE))
|
||||
|| (outpos + length > DATA_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (command) {
|
||||
// write uncompressed bytes
|
||||
// (note: i had to go back to using loops for all of these because memcpy/memmove
|
||||
|
@ -250,12 +269,15 @@ size_t unpack(uint8_t *packed, uint8_t *unpacked) {
|
|||
}
|
||||
|
||||
// Decompress data from an offset into a file
|
||||
size_t unpack_from_file (FILE *file, unsigned int offset, uint8_t *unpacked) {
|
||||
size_t unpack_from_file (FILE *file, size_t offset, uint8_t *unpacked) {
|
||||
uint8_t packed[DATA_SIZE];
|
||||
|
||||
fseek(file, offset, SEEK_SET);
|
||||
fread((void*)packed, DATA_SIZE, 1, file);
|
||||
return unpack(packed, unpacked);
|
||||
if (!feof(file))
|
||||
return unpack(packed, unpacked);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reverses the order of bits in a byte.
|
||||
|
@ -280,7 +302,7 @@ uint8_t rotate (uint8_t i) {
|
|||
// fast enables faster compression by ignoring sequence RLE.
|
||||
rle_t rle_check (uint8_t *start, uint8_t *current, uint32_t insize, int fast) {
|
||||
rle_t candidate = { 0, 0, 0 };
|
||||
int size;
|
||||
size_t size;
|
||||
|
||||
// check for possible 8-bit RLE
|
||||
for (size = 0; size <= LONG_RUN_SIZE && current + size < start + insize; size++)
|
||||
|
|
|
@ -21,10 +21,10 @@ extern "C" {
|
|||
#define RUN_SIZE 32
|
||||
#define LONG_RUN_SIZE 1024
|
||||
|
||||
size_t pack (uint8_t *unpacked, uint32_t inputsize, uint8_t *packed, int fast);
|
||||
size_t pack (uint8_t *unpacked, size_t inputsize, uint8_t *packed, int fast);
|
||||
size_t unpack (uint8_t *packed, uint8_t *unpacked);
|
||||
|
||||
size_t unpack_from_file (FILE *file, unsigned int offset, uint8_t *unpacked);
|
||||
size_t unpack_from_file (FILE *file, size_t offset, uint8_t *unpacked);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
29
exhal.c
29
exhal.c
|
@ -39,20 +39,31 @@ int main (int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
size_t outputsize;
|
||||
uint32_t fileoffset;
|
||||
uint8_t unpacked[DATA_SIZE];
|
||||
size_t outputsize, fileoffset;
|
||||
uint8_t unpacked[DATA_SIZE] = {0};
|
||||
|
||||
fileoffset = strtol(argv[2], NULL, 0);
|
||||
|
||||
// decompress the file
|
||||
outputsize = unpack_from_file(infile, fileoffset, unpacked);
|
||||
fseek(infile, 0, SEEK_END);
|
||||
if (fileoffset < ftell(infile)) {
|
||||
outputsize = unpack_from_file(infile, fileoffset, unpacked);
|
||||
} else {
|
||||
printf("Error: Unable to decompress %s because an invalid offset was specified\n"
|
||||
" (must be between zero and 0x%X).\n", argv[1], ftell(infile));
|
||||
outputsize = 0;
|
||||
}
|
||||
|
||||
// write the uncompressed data to the file
|
||||
fseek(outfile, 0, SEEK_SET);
|
||||
fwrite((const void*)unpacked, 1, outputsize, outfile);
|
||||
|
||||
printf("Uncompressed size: %zd bytes\n", outputsize);
|
||||
if (outputsize) {
|
||||
// write the uncompressed data to the file
|
||||
fseek(outfile, 0, SEEK_SET);
|
||||
fwrite((const void*)unpacked, 1, outputsize, outfile);
|
||||
|
||||
printf("Uncompressed size: %zu bytes\n", outputsize);
|
||||
} else {
|
||||
printf("Error: Unable to decompress %s because the output would have been larger than\n"
|
||||
" 64 kb. The input at 0x%X is likely not valid compressed data.\n", argv[1], fileoffset);
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
|
|
29
inhal.c
29
inhal.c
|
@ -81,7 +81,11 @@ int main (int argc, char **argv) {
|
|||
if (inputsize > DATA_SIZE) {
|
||||
printf("Error: File must be a maximum of 65,536 bytes!\n");
|
||||
exit(-1);
|
||||
} else if (!inputsize) {
|
||||
printf("Error: Input file is empty!\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// read the file
|
||||
fseek(infile, 0, SEEK_SET);
|
||||
fread(unpacked, sizeof(uint8_t), inputsize, infile);
|
||||
|
@ -90,16 +94,21 @@ int main (int argc, char **argv) {
|
|||
clock_t time = clock();
|
||||
outputsize = pack(unpacked, inputsize, packed, fast);
|
||||
time = clock() - time;
|
||||
|
||||
// write the compressed data to the file
|
||||
fseek(outfile, fileoffset, SEEK_SET);
|
||||
fwrite((const void*)packed, 1, outputsize, outfile);
|
||||
|
||||
printf("Compressed size: % zd bytes\n", outputsize);
|
||||
printf("Compression ratio: %4.2f%%\n", 100 * (double)outputsize / inputsize);
|
||||
printf("Compression time: %4.3f seconds\n\n", (double)time / CLOCKS_PER_SEC);
|
||||
|
||||
printf("Inserted at 0x%06X - 0x%06lX\n", fileoffset, ftell(outfile) - 1);
|
||||
|
||||
if (outputsize) {
|
||||
// write the compressed data to the file
|
||||
fseek(outfile, fileoffset, SEEK_SET);
|
||||
fwrite((const void*)packed, 1, outputsize, outfile);
|
||||
|
||||
printf("Compressed size: % zu bytes\n", outputsize);
|
||||
printf("Compression ratio: %4.2f%%\n", 100 * (double)outputsize / inputsize);
|
||||
printf("Compression time: %4.3f seconds\n\n", (double)time / CLOCKS_PER_SEC);
|
||||
|
||||
printf("Inserted at 0x%06X - 0x%06lX\n", fileoffset, ftell(outfile) - 1);
|
||||
} else {
|
||||
printf("Error: File could not be compressed because the resulting compressed data would\n"
|
||||
" have been larger than 64 kb.\n");
|
||||
}
|
||||
|
||||
fclose(infile);
|
||||
fclose(outfile);
|
||||
|
|
Loading…
Reference in a new issue