mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 04:28:37 +00:00
cleanup unpacking function and get rid of an old hack to prevent buffer overflows.
svn-id: r20884
This commit is contained in:
parent
bb4d463138
commit
164f35b878
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user