more consistent types, some bounds checking

This commit is contained in:
devinacker 2013-11-13 22:31:06 -05:00
parent d8e6310bb5
commit fb163a5b08
4 changed files with 70 additions and 28 deletions

View file

@ -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++)

View file

@ -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
View file

@ -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
View file

@ -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);