mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-16 01:11:28 +00:00
cache1d.c: more meaning-preserving transformations, patch up one oob access.
lzwcompress can access one byte after lzwrawbuf[LZWSIZE] when provided with an uncompleng of LZWSIZE, so we increase that array's size by one. git-svn-id: https://svn.eduke32.com/eduke32@2369 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
3dfb04d343
commit
24c4364e3d
1 changed files with 64 additions and 37 deletions
|
@ -1170,7 +1170,8 @@ failure:
|
||||||
#define LZWSIZE 16384 //Watch out for shorts!
|
#define LZWSIZE 16384 //Watch out for shorts!
|
||||||
#define LZWSIZEPAD (LZWSIZE+(LZWSIZE>>4))
|
#define LZWSIZEPAD (LZWSIZE+(LZWSIZE>>4))
|
||||||
|
|
||||||
static char lzwtmpbuf[LZWSIZEPAD], lzwrawbuf[LZWSIZE], lzwcompbuf[LZWSIZEPAD];
|
// lzwrawbuf LZWSIZE+1: see (*) below
|
||||||
|
static char lzwtmpbuf[LZWSIZEPAD], lzwrawbuf[LZWSIZE+1], lzwcompbuf[LZWSIZEPAD];
|
||||||
static int16_t lzwbuf2[LZWSIZEPAD], lzwbuf3[LZWSIZEPAD];
|
static int16_t lzwbuf2[LZWSIZEPAD], lzwbuf3[LZWSIZEPAD];
|
||||||
|
|
||||||
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf);
|
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf);
|
||||||
|
@ -1182,14 +1183,17 @@ int32_t kdfread(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
||||||
int16_t leng;
|
int16_t leng;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
|
if (dasizeof > LZWSIZE)
|
||||||
|
{
|
||||||
|
count *= dasizeof;
|
||||||
|
dasizeof = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = (char *)buffer;
|
ptr = (char *)buffer;
|
||||||
|
|
||||||
if (kread(fil,&leng,2) != 2) return -1; leng = B_LITTLE16(leng);
|
if (kread(fil,&leng,2) != 2) return -1; leng = B_LITTLE16(leng);
|
||||||
if (kread(fil,lzwcompbuf,(int32_t)leng) != leng) return -1;
|
if (kread(fil,lzwcompbuf,(int32_t)leng) != leng) return -1;
|
||||||
|
k = 0; kgoal = lzwuncompress(lzwcompbuf,(int32_t)leng,lzwrawbuf);
|
||||||
k = 0;
|
|
||||||
kgoal = lzwuncompress(lzwcompbuf,(int32_t)leng,lzwrawbuf);
|
|
||||||
|
|
||||||
copybufbyte(lzwrawbuf,ptr,(int32_t)dasizeof);
|
copybufbyte(lzwrawbuf,ptr,(int32_t)dasizeof);
|
||||||
k += (int32_t)dasizeof;
|
k += (int32_t)dasizeof;
|
||||||
|
@ -1213,57 +1217,69 @@ int32_t kdfread(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t compress_part(uint32_t k, BFILE *fil)
|
||||||
|
{
|
||||||
|
int16_t leng, swleng;
|
||||||
|
|
||||||
|
leng = (int16_t)lzwcompress(lzwrawbuf,k,lzwcompbuf); swleng = B_LITTLE16(leng);
|
||||||
|
Bfwrite(&swleng,2,1,fil); Bfwrite(lzwcompbuf,(int32_t)leng,1,fil);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void dfwrite(const void *buffer, bsize_t dasizeof, bsize_t count, BFILE *fil)
|
void dfwrite(const void *buffer, bsize_t dasizeof, bsize_t count, BFILE *fil)
|
||||||
{
|
{
|
||||||
uint32_t i, j, k;
|
uint32_t i, j, k;
|
||||||
int16_t leng, swleng;
|
|
||||||
const char *ptr;
|
const char *ptr;
|
||||||
|
|
||||||
if (dasizeof > LZWSIZE) { count *= dasizeof; dasizeof = 1; }
|
if (dasizeof > LZWSIZE)
|
||||||
|
{
|
||||||
|
count *= dasizeof;
|
||||||
|
dasizeof = 1;
|
||||||
|
}
|
||||||
|
|
||||||
ptr = buffer;
|
ptr = buffer;
|
||||||
|
|
||||||
copybufbyte(ptr,lzwrawbuf,(int32_t)dasizeof);
|
Bmemcpy(lzwrawbuf, ptr, (int32_t)dasizeof);
|
||||||
k = dasizeof;
|
|
||||||
|
|
||||||
|
k = dasizeof;
|
||||||
if (k > LZWSIZE-dasizeof)
|
if (k > LZWSIZE-dasizeof)
|
||||||
{
|
k = compress_part(k, fil);
|
||||||
leng = (int16_t)lzwcompress(lzwrawbuf,k,lzwcompbuf); k = 0; swleng = B_LITTLE16(leng);
|
|
||||||
Bfwrite(&swleng,2,1,fil); Bfwrite(lzwcompbuf,(int32_t)leng,1,fil);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=1; i<count; i++)
|
for (i=1; i<count; i++)
|
||||||
{
|
{
|
||||||
for (j=0; j<dasizeof; j++)
|
for (j=0; j<dasizeof; j++)
|
||||||
lzwrawbuf[j+k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
lzwrawbuf[j+k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
||||||
|
|
||||||
k += dasizeof;
|
k += dasizeof;
|
||||||
if (k > LZWSIZE-dasizeof)
|
if (k > LZWSIZE-dasizeof)
|
||||||
{
|
k = compress_part(k, fil);
|
||||||
leng = (int16_t)lzwcompress(lzwrawbuf,k,lzwcompbuf); k = 0; swleng = B_LITTLE16(leng);
|
|
||||||
Bfwrite(&swleng,2,1,fil); Bfwrite(lzwcompbuf,(int32_t)leng,1,fil);
|
|
||||||
}
|
|
||||||
ptr += dasizeof;
|
ptr += dasizeof;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k > 0)
|
if (k > 0)
|
||||||
{
|
compress_part(k, fil);
|
||||||
leng = (int16_t)lzwcompress(lzwrawbuf,k,lzwcompbuf); swleng = B_LITTLE16(leng);
|
|
||||||
Bfwrite(&swleng,2,1,fil); Bfwrite(lzwcompbuf,(int32_t)leng,1,fil);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf)
|
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf)
|
||||||
{
|
{
|
||||||
int32_t i, addr, newaddr, addrcnt, *intptr;
|
int32_t i, addr, addrcnt, *intptr;
|
||||||
int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
|
int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
|
||||||
int16_t *shortptr;
|
int16_t *shortptr;
|
||||||
|
|
||||||
|
int16_t *const lzwcodehead = lzwbuf2;
|
||||||
|
int16_t *const lzwcodenext = lzwbuf3;
|
||||||
|
|
||||||
for (i=255; i>=0; i--)
|
for (i=255; i>=0; i--)
|
||||||
{
|
{
|
||||||
lzwtmpbuf[i] = i;
|
lzwtmpbuf[i] = i;
|
||||||
lzwbuf3[i] = (i+1)&255;
|
lzwcodenext[i] = (i+1)&255;
|
||||||
lzwbuf2[i] = -1;
|
lzwcodehead[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearbuf(lzwoutbuf,((uncompleng+15)+3)>>2,0L);
|
Bmemset(lzwoutbuf, 0, 4+uncompleng+1);
|
||||||
|
// clearbuf(lzwoutbuf,((uncompleng+15)+3)>>2,0L);
|
||||||
|
|
||||||
addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
|
addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
|
||||||
numbits = 8; oneupnumbits = (1<<8);
|
numbits = 8; oneupnumbits = (1<<8);
|
||||||
|
@ -1272,27 +1288,38 @@ static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwou
|
||||||
addr = lzwinbuf[bytecnt1];
|
addr = lzwinbuf[bytecnt1];
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
int32_t newaddr;
|
||||||
|
|
||||||
bytecnt1++;
|
bytecnt1++;
|
||||||
if (bytecnt1 == uncompleng) break;
|
if (bytecnt1 == uncompleng)
|
||||||
|
break; // (*) see XXX below
|
||||||
|
|
||||||
if (lzwbuf2[addr] < 0) {lzwbuf2[addr] = addrcnt; break;}
|
if (lzwcodehead[addr] < 0)
|
||||||
|
|
||||||
newaddr = lzwbuf2[addr];
|
|
||||||
while (lzwtmpbuf[newaddr] != lzwinbuf[bytecnt1])
|
|
||||||
{
|
{
|
||||||
int32_t zx = lzwbuf3[newaddr];
|
lzwcodehead[addr] = addrcnt;
|
||||||
if (zx < 0) {lzwbuf3[newaddr] = addrcnt; break;}
|
break;
|
||||||
newaddr = zx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lzwbuf3[newaddr] == addrcnt) break;
|
newaddr = lzwcodehead[addr];
|
||||||
|
while (lzwtmpbuf[newaddr] != lzwinbuf[bytecnt1])
|
||||||
|
{
|
||||||
|
if (lzwcodenext[newaddr] < 0)
|
||||||
|
{
|
||||||
|
lzwcodenext[newaddr] = addrcnt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
newaddr = lzwcodenext[newaddr];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lzwcodenext[newaddr] == addrcnt)
|
||||||
|
break;
|
||||||
addr = newaddr;
|
addr = newaddr;
|
||||||
}
|
}
|
||||||
while (addr >= 0);
|
while (addr >= 0);
|
||||||
|
|
||||||
lzwtmpbuf[addrcnt] = lzwinbuf[bytecnt1];
|
lzwtmpbuf[addrcnt] = lzwinbuf[bytecnt1]; // XXX: potential oob access of lzwinbuf via (*) above
|
||||||
lzwbuf2[addrcnt] = -1;
|
lzwcodehead[addrcnt] = -1;
|
||||||
lzwbuf3[addrcnt] = -1;
|
lzwcodenext[addrcnt] = -1;
|
||||||
|
|
||||||
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
||||||
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
||||||
|
|
Loading…
Reference in a new issue