cleanup unpacking function and get rid of an old hack to prevent buffer overflows.

svn-id: r20884
This commit is contained in:
Gregory Montoir 2006-02-25 18:26:16 +00:00
parent bb4d463138
commit 164f35b878
4 changed files with 85 additions and 125 deletions

View File

@ -203,14 +203,10 @@ uint8 *readBundleFile(int16 foundFileIdx) {
if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) {
uint8 *unpackBuffer;
uint16 realSize;
unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize + 500);
unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize);
readFromPart(foundFileIdx, unpackBuffer);
realSize = READ_BE_UINT32(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4);
decomp(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4, dataPtr + realSize, realSize);
delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize);
free(unpackBuffer);
} else {
readFromPart(foundFileIdx, dataPtr);

View File

@ -117,7 +117,7 @@ static uint8 *snd_loadBasesonEntry(const char *entryName) {
if (tempData) {
snd_baseSndFile->seek(be->offset, SEEK_SET);
snd_baseSndFile->read(tempData, be->size);
decomp(tempData + be->size - 4, entryData + be->unpackedSize, be->unpackedSize);
delphineUnpack(entryData, tempData, be->size);
free(tempData);
}
} else {

View File

@ -26,130 +26,86 @@
namespace Cine {
uint32 crc; // variable at 5C5A
uint32 bitbucket; // dx:bx
uint16 swap16(uint16 r) {
return (r >> 8) | (r << 8);
static int rcr(UnpackCtx *uc, int CF) {
int rCF = (uc->chk & 1);
uc->chk >>= 1;
if (CF) {
uc->chk |= 0x80000000;
}
return rCF;
}
#define loadd(p, d) {\
d = *(--p);\
d |= (*(--p)) << 8;\
d |= (*(--p)) << 16;\
d |= (*(--p)) << 24;\
}
#define store(p, b) *(--p) = b
#define getbit(p, b) { \
b = bitbucket & 1; \
bitbucket >>= 1; \
if (!bitbucket) { \
loadd(p, bitbucket); \
crc ^= bitbucket; \
b = bitbucket & 1; \
bitbucket >>= 1; \
bitbucket |= 0x80000000;\
} \
static int nextChunk(UnpackCtx *uc) {
int CF = rcr(uc, 0);
if (uc->chk == 0) {
uc->chk = READ_BE_UINT32(uc->src); uc->src -= 4;
uc->crc ^= uc->chk;
CF = rcr(uc, 1);
}
return CF;
}
#define loadbits(p, b) { \
b = 0; \
do { \
getbit(p, bit); \
b <<= 1; \
b |= bit; \
nbits--; \
} while (nbits); \
static uint16 getCode(UnpackCtx *uc, uint8 numChunks) {
uint16 c = 0;
while (numChunks--) {
c <<= 1;
if (nextChunk(uc)) {
c |= 1;
}
}
return c;
}
int decomp(uint8 *in, uint8 *out, int size) {
uint8 bit; // Carry flag
uint8 nbits; // cl
uint8 byte = 0; // ch
uint16 counter; // bp
uint16 var = 0; // variable at 5C58
uint16 ptr;
uint16 flags;
enum {
DO_COPY,
DO_UNPACK
} action;
loadd(in, crc);
loadd(in, bitbucket);
crc ^= bitbucket;
do { // 5A4C
getbit(in, bit);
if (!bit) { // 5A94
getbit(in, bit);
if (!bit) { // 5AC8
nbits = 3;
byte = 0;
action = DO_COPY;
} else { // 5ACA
var = 1;
nbits = 8;
action = DO_UNPACK;
}
} else { // 5B4F
nbits = 2;
loadbits(in, flags);
if (flags < 2) {
nbits = flags + 9; // 5BC3
var = flags + 2;
action = DO_UNPACK;
} else if (flags == 3) {
nbits = 8; // 5B4A
byte = 8;
action = DO_COPY;
} else {
nbits = 8;
loadbits(in, var);
nbits = 12;
action = DO_UNPACK;
}
}
switch (action) {
case DO_COPY:
{
// 5AD1
loadbits(in, counter); // 5AFD
counter += byte;
counter++;
size -= counter;
do {
nbits = 8;
loadbits(in, byte); // 5B3F
store(out, byte);
counter--;
} while (counter); // 5B45
break;
}
case DO_UNPACK:
// 5BD3
loadbits(in, ptr); // 5BFF
counter = var + 1;
size -= counter;
do {
byte = *(out + ptr - 1);
store(out, byte);
counter--;
} while (counter);
}
} while (size > 0);
// 5C32
// ???
if (crc) {
return -1;
} else {
return 0;
static void unpackHelper1(UnpackCtx *uc, uint8 numChunks, uint8 addCount) {
uint16 count = getCode(uc, numChunks) + addCount + 1;
uc->datasize -= count;
while (count--) {
*uc->dst = (uint8)getCode(uc, 8);
--uc->dst;
}
}
static void unpackHelper2(UnpackCtx *uc, uint8 numChunks) {
uint16 i = getCode(uc, numChunks);
uint16 count = uc->size + 1;
uc->datasize -= count;
while (count--) {
*uc->dst = *(uc->dst + i);
--uc->dst;
}
}
bool delphineUnpack(uint8 *dst, const uint8 *src, int len) {
UnpackCtx uc;
uc.src = src + len - 4;
uc.datasize = READ_BE_UINT32(uc.src); uc.src -= 4;
uc.dst = dst + uc.datasize - 1;
uc.size = 0;
uc.crc = READ_BE_UINT32(uc.src); uc.src -= 4;
uc.chk = READ_BE_UINT32(uc.src); uc.src -= 4;
uc.crc ^= uc.chk;
do {
if (!nextChunk(&uc)) {
uc.size = 1;
if (!nextChunk(&uc)) {
unpackHelper1(&uc, 3, 0);
} else {
unpackHelper2(&uc, 8);
}
} else {
uint16 c = getCode(&uc, 2);
if (c == 3) {
unpackHelper1(&uc, 8, 8);
} else if (c < 2) {
uc.size = c + 2;
unpackHelper2(&uc, c + 9);
} else {
uc.size = getCode(&uc, 8);
unpackHelper2(&uc, 12);
}
}
} while (uc.datasize > 0);
return uc.crc == 0;
}
} // End of namespace Cine

View File

@ -30,7 +30,15 @@
namespace Cine {
int decomp(uint8 *in, uint8 *out, int size);
struct UnpackCtx {
int size, datasize;
uint32 crc;
uint32 chk;
uint8 *dst;
const uint8 *src;
};
bool delphineUnpack(uint8 *dst, const uint8 *src, int len);
} // End of namespace Cine