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) { if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) {
uint8 *unpackBuffer; uint8 *unpackBuffer;
uint16 realSize;
unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize + 500); unpackBuffer = (uint8 *)malloc(partBuffer[foundFileIdx].packedSize);
readFromPart(foundFileIdx, unpackBuffer); readFromPart(foundFileIdx, unpackBuffer);
delphineUnpack(dataPtr, unpackBuffer, partBuffer[foundFileIdx].packedSize);
realSize = READ_BE_UINT32(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4);
decomp(unpackBuffer + partBuffer[foundFileIdx].packedSize - 4, dataPtr + realSize, realSize);
free(unpackBuffer); free(unpackBuffer);
} else { } else {
readFromPart(foundFileIdx, dataPtr); readFromPart(foundFileIdx, dataPtr);

View File

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

View File

@ -26,130 +26,86 @@
namespace Cine { namespace Cine {
uint32 crc; // variable at 5C5A static int rcr(UnpackCtx *uc, int CF) {
uint32 bitbucket; // dx:bx int rCF = (uc->chk & 1);
uc->chk >>= 1;
uint16 swap16(uint16 r) { if (CF) {
return (r >> 8) | (r << 8); uc->chk |= 0x80000000;
}
return rCF;
} }
#define loadd(p, d) {\ static int nextChunk(UnpackCtx *uc) {
d = *(--p);\ int CF = rcr(uc, 0);
d |= (*(--p)) << 8;\ if (uc->chk == 0) {
d |= (*(--p)) << 16;\ uc->chk = READ_BE_UINT32(uc->src); uc->src -= 4;
d |= (*(--p)) << 24;\ uc->crc ^= uc->chk;
} CF = rcr(uc, 1);
#define store(p, b) *(--p) = b }
#define getbit(p, b) { \ return CF;
b = bitbucket & 1; \
bitbucket >>= 1; \
if (!bitbucket) { \
loadd(p, bitbucket); \
crc ^= bitbucket; \
b = bitbucket & 1; \
bitbucket >>= 1; \
bitbucket |= 0x80000000;\
} \
} }
#define loadbits(p, b) { \ static uint16 getCode(UnpackCtx *uc, uint8 numChunks) {
b = 0; \ uint16 c = 0;
do { \ while (numChunks--) {
getbit(p, bit); \ c <<= 1;
b <<= 1; \ if (nextChunk(uc)) {
b |= bit; \ c |= 1;
nbits--; \ }
} while (nbits); \ }
return c;
} }
int decomp(uint8 *in, uint8 *out, int size) { static void unpackHelper1(UnpackCtx *uc, uint8 numChunks, uint8 addCount) {
uint8 bit; // Carry flag uint16 count = getCode(uc, numChunks) + addCount + 1;
uint8 nbits; // cl uc->datasize -= count;
uint8 byte = 0; // ch while (count--) {
uint16 counter; // bp *uc->dst = (uint8)getCode(uc, 8);
uint16 var = 0; // variable at 5C58 --uc->dst;
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 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 } // End of namespace Cine

View File

@ -30,7 +30,15 @@
namespace Cine { 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 } // End of namespace Cine