|
|
|
@ -75,18 +75,20 @@ Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);
|
|
|
|
|
|
|
|
|
|
/*Set error var to the error code, and return it.*/
|
|
|
|
|
#define CERROR_RETURN_ERROR(errorvar, code) \
|
|
|
|
|
do \
|
|
|
|
|
{ \
|
|
|
|
|
errorvar = code; \
|
|
|
|
|
return code; \
|
|
|
|
|
}
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/*Try the code, if it returns error, also return the error.*/
|
|
|
|
|
#define CERROR_TRY_RETURN(call) \
|
|
|
|
|
do \
|
|
|
|
|
{ \
|
|
|
|
|
unsigned error = call; \
|
|
|
|
|
if (error) \
|
|
|
|
|
return error; \
|
|
|
|
|
}
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
About uivector, ucvector and string:
|
|
|
|
@ -1066,7 +1068,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
|
|
|
|
|
bitlen_cl = (unsigned*)malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));
|
|
|
|
|
if (!bitlen_cl)
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_CODE_LENGTH_CODES; i++)
|
|
|
|
|
{
|
|
|
|
@ -1084,7 +1086,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
bitlen_ll = (unsigned*)malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
|
|
|
|
|
bitlen_d = (unsigned*)malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
|
|
|
|
|
if (!bitlen_ll || !bitlen_d)
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
for (i = 0; i < NUM_DEFLATE_CODE_SYMBOLS; i++)
|
|
|
|
|
bitlen_ll[i] = 0;
|
|
|
|
|
for (i = 0; i < NUM_DISTANCE_SYMBOLS; i++)
|
|
|
|
@ -1110,9 +1112,9 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
unsigned value; /*set value to the previous code*/
|
|
|
|
|
|
|
|
|
|
if (*bp >= inbitlength)
|
|
|
|
|
ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
|
|
|
|
|
ERROR_BREAK(50) /*error, bit pointer jumps past memory*/
|
|
|
|
|
if (i == 0)
|
|
|
|
|
ERROR_BREAK(54); /*can't repeat previous if i is 0*/
|
|
|
|
|
ERROR_BREAK(54) /*can't repeat previous if i is 0*/
|
|
|
|
|
|
|
|
|
|
replength += readBitsFromStream(bp, in, 2);
|
|
|
|
|
|
|
|
|
@ -1124,7 +1126,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
for (n = 0; n < replength; n++)
|
|
|
|
|
{
|
|
|
|
|
if (i >= HLIT + HDIST)
|
|
|
|
|
ERROR_BREAK(13); /*error: i is larger than the amount of codes*/
|
|
|
|
|
ERROR_BREAK(13) /*error: i is larger than the amount of codes*/
|
|
|
|
|
if (i < HLIT)
|
|
|
|
|
bitlen_ll[i] = value;
|
|
|
|
|
else
|
|
|
|
@ -1136,7 +1138,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
{
|
|
|
|
|
unsigned replength = 3; /*read in the bits that indicate repeat length*/
|
|
|
|
|
if (*bp >= inbitlength)
|
|
|
|
|
ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
|
|
|
|
|
ERROR_BREAK(50) /*error, bit pointer jumps past memory*/
|
|
|
|
|
|
|
|
|
|
replength += readBitsFromStream(bp, in, 3);
|
|
|
|
|
|
|
|
|
@ -1144,7 +1146,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
for (n = 0; n < replength; n++)
|
|
|
|
|
{
|
|
|
|
|
if (i >= HLIT + HDIST)
|
|
|
|
|
ERROR_BREAK(14); /*error: i is larger than the amount of codes*/
|
|
|
|
|
ERROR_BREAK(14) /*error: i is larger than the amount of codes*/
|
|
|
|
|
|
|
|
|
|
if (i < HLIT)
|
|
|
|
|
bitlen_ll[i] = 0;
|
|
|
|
@ -1157,7 +1159,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
{
|
|
|
|
|
unsigned replength = 11; /*read in the bits that indicate repeat length*/
|
|
|
|
|
if (*bp >= inbitlength)
|
|
|
|
|
ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
|
|
|
|
|
ERROR_BREAK(50) /*error, bit pointer jumps past memory*/
|
|
|
|
|
|
|
|
|
|
replength += readBitsFromStream(bp, in, 7);
|
|
|
|
|
|
|
|
|
@ -1165,7 +1167,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
for (n = 0; n < replength; n++)
|
|
|
|
|
{
|
|
|
|
|
if (i >= HLIT + HDIST)
|
|
|
|
|
ERROR_BREAK(15); /*error: i is larger than the amount of codes*/
|
|
|
|
|
ERROR_BREAK(15) /*error: i is larger than the amount of codes*/
|
|
|
|
|
|
|
|
|
|
if (i < HLIT)
|
|
|
|
|
bitlen_ll[i] = 0;
|
|
|
|
@ -1192,7 +1194,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (bitlen_ll[256] == 0)
|
|
|
|
|
ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/
|
|
|
|
|
ERROR_BREAK(64) /*the length of the end code 256 must be larger than 0*/
|
|
|
|
|
|
|
|
|
|
/*now we've finally got HLIT and HDIST, so generate the code trees, and the function is
|
|
|
|
|
* done*/
|
|
|
|
@ -1246,7 +1248,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
|
|
|
|
|
/*ucvector_push_back would do the same, but for some reason the two lines below run 10%
|
|
|
|
|
* faster*/
|
|
|
|
|
if (!ucvector_resize(out, (*pos) + 1))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
out->data[*pos] = (unsigned char)code_ll;
|
|
|
|
|
(*pos)++;
|
|
|
|
|
}
|
|
|
|
@ -1263,7 +1265,7 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
|
|
|
|
|
/*part 2: get extra bits and add the value of that to length*/
|
|
|
|
|
numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
|
|
|
|
|
if (*bp >= inbitlength)
|
|
|
|
|
ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
|
|
|
|
|
ERROR_BREAK(51) /*error, bit pointer will jump past memory*/
|
|
|
|
|
length += readBitsFromStream(bp, in, numextrabits_l);
|
|
|
|
|
|
|
|
|
|
/*part 3: get distance code*/
|
|
|
|
@ -1286,18 +1288,18 @@ static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size
|
|
|
|
|
/*part 4: get extra bits from distance*/
|
|
|
|
|
numextrabits_d = DISTANCEEXTRA[code_d];
|
|
|
|
|
if (*bp >= inbitlength)
|
|
|
|
|
ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
|
|
|
|
|
ERROR_BREAK(51) /*error, bit pointer will jump past memory*/
|
|
|
|
|
|
|
|
|
|
distance += readBitsFromStream(bp, in, numextrabits_d);
|
|
|
|
|
|
|
|
|
|
/*part 5: fill in all the out[n] values based on the length and dist*/
|
|
|
|
|
start = (*pos);
|
|
|
|
|
if (distance > start)
|
|
|
|
|
ERROR_BREAK(52); /*too long backward distance*/
|
|
|
|
|
ERROR_BREAK(52) /*too long backward distance*/
|
|
|
|
|
backward = start - distance;
|
|
|
|
|
|
|
|
|
|
if (!ucvector_resize(out, (*pos) + length))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
for (forward = 0; forward < length; forward++)
|
|
|
|
|
{
|
|
|
|
|
out->data[(*pos)] = out->data[backward];
|
|
|
|
@ -1751,12 +1753,12 @@ static unsigned encodeLZ77(uivector* out, Hash* hash, const unsigned char* in, s
|
|
|
|
|
{
|
|
|
|
|
lazy = 0;
|
|
|
|
|
if (pos == 0)
|
|
|
|
|
ERROR_BREAK(81);
|
|
|
|
|
ERROR_BREAK(81)
|
|
|
|
|
if (length > lazylength + 1)
|
|
|
|
|
{
|
|
|
|
|
/*push the previous character as literal*/
|
|
|
|
|
if (!uivector_push_back(out, in[pos - 1]))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -1770,20 +1772,20 @@ static unsigned encodeLZ77(uivector* out, Hash* hash, const unsigned char* in, s
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (length >= 3 && offset > windowsize)
|
|
|
|
|
ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
|
|
|
|
|
ERROR_BREAK(86 /*too big (or overflown negative) offset*/)
|
|
|
|
|
|
|
|
|
|
/*encode it as length/distance pair or literal value*/
|
|
|
|
|
if (length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/
|
|
|
|
|
{
|
|
|
|
|
if (!uivector_push_back(out, in[pos]))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
}
|
|
|
|
|
else if (length < minmatch || (length == 3 && offset > 4096))
|
|
|
|
|
{
|
|
|
|
|
/*compensate for the fact that longer offsets have more extra bits, a
|
|
|
|
|
length of only 3 may be not worth it then*/
|
|
|
|
|
if (!uivector_push_back(out, in[pos]))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
@ -1963,18 +1965,18 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!uivector_resize(&lz77_encoded, datasize))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
if (!lz77_encoded.data)
|
|
|
|
|
ERROR_BREAK(83 /* alloc fail */);
|
|
|
|
|
ERROR_BREAK(83 /* alloc fail */)
|
|
|
|
|
|
|
|
|
|
for (i = datapos; i < dataend; i++)
|
|
|
|
|
lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!uivector_resizev(&frequencies_ll, 286, 0))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
if (!uivector_resizev(&frequencies_d, 30, 0))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
|
|
|
|
|
/*Count the frequencies of lit, len and dist codes*/
|
|
|
|
|
for (i = 0; i < lz77_encoded.size; i++)
|
|
|
|
@ -1982,7 +1984,7 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
unsigned symbol;
|
|
|
|
|
|
|
|
|
|
if (!lz77_encoded.data)
|
|
|
|
|
ERROR_BREAK(83 /* alloc fail */);
|
|
|
|
|
ERROR_BREAK(83 /* alloc fail */)
|
|
|
|
|
|
|
|
|
|
symbol = lz77_encoded.data[i];
|
|
|
|
|
frequencies_ll.data[symbol]++;
|
|
|
|
@ -2073,7 +2075,7 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
/*generate tree_cl, the huffmantree of huffmantrees*/
|
|
|
|
|
|
|
|
|
|
if (!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
for (i = 0; i < bitlen_lld_e.size; i++)
|
|
|
|
|
{
|
|
|
|
|
frequencies_cl.data[bitlen_lld_e.data[i]]++;
|
|
|
|
@ -2089,7 +2091,7 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!uivector_resize(&bitlen_cl, tree_cl.numcodes))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
for (i = 0; i < tree_cl.numcodes && bitlen_cl.data; i++)
|
|
|
|
|
{
|
|
|
|
|
/*lenghts of code length tree is in the order as specified by deflate*/
|
|
|
|
@ -2099,7 +2101,7 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
{
|
|
|
|
|
/*remove zeros at the end, but minimum size must be 4*/
|
|
|
|
|
if (!uivector_resize(&bitlen_cl, bitlen_cl.size - 1))
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/);
|
|
|
|
|
ERROR_BREAK(83 /*alloc fail*/)
|
|
|
|
|
}
|
|
|
|
|
if (error || !bitlen_cl.data)
|
|
|
|
|
break;
|
|
|
|
@ -2161,7 +2163,7 @@ static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, const unsi
|
|
|
|
|
writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
|
|
|
|
|
/*error: the length of the end code 256 must be larger than 0*/
|
|
|
|
|
if (HuffmanTree_getLength(&tree_ll, 256) == 0)
|
|
|
|
|
ERROR_BREAK(64);
|
|
|
|
|
ERROR_BREAK(64)
|
|
|
|
|
|
|
|
|
|
/*write the end code*/
|
|
|
|
|
addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256),
|
|
|
|
@ -3376,7 +3378,6 @@ static unsigned rgba8ToPixel(unsigned char* out, size_t i, const LodePNGColorMod
|
|
|
|
|
if (mode->colortype == LCT_GREY)
|
|
|
|
|
{
|
|
|
|
|
unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/
|
|
|
|
|
;
|
|
|
|
|
if (mode->bitdepth == 8)
|
|
|
|
|
out[i] = grey;
|
|
|
|
|
else if (mode->bitdepth == 16)
|
|
|
|
@ -3416,7 +3417,6 @@ static unsigned rgba8ToPixel(unsigned char* out, size_t i, const LodePNGColorMod
|
|
|
|
|
else if (mode->colortype == LCT_GREY_ALPHA)
|
|
|
|
|
{
|
|
|
|
|
unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/
|
|
|
|
|
;
|
|
|
|
|
if (mode->bitdepth == 8)
|
|
|
|
|
{
|
|
|
|
|
out[i * 2 + 0] = grey;
|
|
|
|
@ -3456,7 +3456,6 @@ static void rgba16ToPixel(unsigned char* out, size_t i, const LodePNGColorMode*
|
|
|
|
|
if (mode->colortype == LCT_GREY)
|
|
|
|
|
{
|
|
|
|
|
unsigned short grey = r; /*((unsigned)r + g + b) / 3*/
|
|
|
|
|
;
|
|
|
|
|
out[i * 2 + 0] = (grey >> 8) & 255;
|
|
|
|
|
out[i * 2 + 1] = grey & 255;
|
|
|
|
|
}
|
|
|
|
@ -3472,7 +3471,6 @@ static void rgba16ToPixel(unsigned char* out, size_t i, const LodePNGColorMode*
|
|
|
|
|
else if (mode->colortype == LCT_GREY_ALPHA)
|
|
|
|
|
{
|
|
|
|
|
unsigned short grey = r; /*((unsigned)r + g + b) / 3*/
|
|
|
|
|
;
|
|
|
|
|
out[i * 4 + 0] = (grey >> 8) & 255;
|
|
|
|
|
out[i * 4 + 1] = grey & 255;
|
|
|
|
|
out[i * 4 + 2] = (a >> 8) & 255;
|
|
|
|
@ -4692,11 +4690,11 @@ static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, siz
|
|
|
|
|
/*even though it's not allowed by the standard, no error is thrown if
|
|
|
|
|
there's no null termination char, if the text is empty*/
|
|
|
|
|
if (length < 1 || length > 79)
|
|
|
|
|
CERROR_BREAK(error, 89); /*keyword too short or long*/
|
|
|
|
|
CERROR_BREAK(error, 89) /*keyword too short or long*/
|
|
|
|
|
|
|
|
|
|
key = (char*)malloc(length + 1);
|
|
|
|
|
if (!key)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
key[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4707,7 +4705,7 @@ static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, siz
|
|
|
|
|
length = chunkLength < string2_begin ? 0 : chunkLength - string2_begin;
|
|
|
|
|
str = (char*)malloc(length + 1);
|
|
|
|
|
if (!str)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
str[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4740,26 +4738,25 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
while (!error) /*not really a while loop, only used to break on error*/
|
|
|
|
|
{
|
|
|
|
|
for (length = 0; length < chunkLength && data[length] != 0; length++)
|
|
|
|
|
;
|
|
|
|
|
if (length + 2 >= chunkLength)
|
|
|
|
|
CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
|
|
|
|
CERROR_BREAK(error, 75) /*no null termination, corrupt?*/
|
|
|
|
|
if (length < 1 || length > 79)
|
|
|
|
|
CERROR_BREAK(error, 89); /*keyword too short or long*/
|
|
|
|
|
CERROR_BREAK(error, 89) /*keyword too short or long*/
|
|
|
|
|
|
|
|
|
|
key = (char*)malloc(length + 1);
|
|
|
|
|
if (!key)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
key[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
|
key[i] = (char)data[i];
|
|
|
|
|
|
|
|
|
|
if (data[length + 1] != 0)
|
|
|
|
|
CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
|
|
|
|
|
CERROR_BREAK(error, 72) /*the 0 byte indicating compression must be 0*/
|
|
|
|
|
|
|
|
|
|
string2_begin = length + 2;
|
|
|
|
|
if (string2_begin > chunkLength)
|
|
|
|
|
CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
|
|
|
|
CERROR_BREAK(error, 75) /*no null termination, corrupt?*/
|
|
|
|
|
|
|
|
|
|
length = chunkLength - string2_begin;
|
|
|
|
|
/*will fail if zlib error, e.g. if length is too small*/
|
|
|
|
@ -4768,7 +4765,7 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
if (error)
|
|
|
|
|
break;
|
|
|
|
|
if (!ucvector_push_back(&decoded, 0))
|
|
|
|
|
ERROR_BREAK(83);
|
|
|
|
|
ERROR_BREAK(83)
|
|
|
|
|
|
|
|
|
|
error = lodepng_add_text(info, key, (char*)decoded.data);
|
|
|
|
|
|
|
|
|
@ -4799,19 +4796,19 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
it'd still fail with other error checks below if it's too short. This just gives a different
|
|
|
|
|
error code.*/
|
|
|
|
|
if (chunkLength < 5)
|
|
|
|
|
CERROR_BREAK(error, 30); /*iTXt chunk too short*/
|
|
|
|
|
CERROR_BREAK(error, 30) /*iTXt chunk too short*/
|
|
|
|
|
|
|
|
|
|
/*read the key*/
|
|
|
|
|
for (length = 0; length < chunkLength && data[length] != 0; length++)
|
|
|
|
|
;
|
|
|
|
|
if (length + 3 >= chunkLength)
|
|
|
|
|
CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/
|
|
|
|
|
CERROR_BREAK(error, 75) /*no null termination char, corrupt?*/
|
|
|
|
|
if (length < 1 || length > 79)
|
|
|
|
|
CERROR_BREAK(error, 89); /*keyword too short or long*/
|
|
|
|
|
CERROR_BREAK(error, 89) /*keyword too short or long*/
|
|
|
|
|
|
|
|
|
|
key = (char*)malloc(length + 1);
|
|
|
|
|
if (!key)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
key[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4820,7 +4817,7 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
/*read the compression method*/
|
|
|
|
|
compressed = data[length + 1];
|
|
|
|
|
if (data[length + 2] != 0)
|
|
|
|
|
CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
|
|
|
|
|
CERROR_BREAK(error, 72) /*the 0 byte indicating compression must be 0*/
|
|
|
|
|
|
|
|
|
|
/*even though it's not allowed by the standard, no error is thrown if
|
|
|
|
|
there's no null termination char, if the text is empty for the next 3 texts*/
|
|
|
|
@ -4833,7 +4830,7 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
|
|
|
|
|
langtag = (char*)malloc(length + 1);
|
|
|
|
|
if (!langtag)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
langtag[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4847,7 +4844,7 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
|
|
|
|
|
transkey = (char*)malloc(length + 1);
|
|
|
|
|
if (!transkey)
|
|
|
|
|
CERROR_BREAK(error, 83); /*alloc fail*/
|
|
|
|
|
CERROR_BREAK(error, 83) /*alloc fail*/
|
|
|
|
|
|
|
|
|
|
transkey[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4868,12 +4865,12 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
|
|
|
|
if (decoded.allocsize < decoded.size)
|
|
|
|
|
decoded.allocsize = decoded.size;
|
|
|
|
|
if (!ucvector_push_back(&decoded, 0))
|
|
|
|
|
CERROR_BREAK(error, 83 /*alloc fail*/);
|
|
|
|
|
CERROR_BREAK(error, 83 /*alloc fail*/)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!ucvector_resize(&decoded, length + 1))
|
|
|
|
|
CERROR_BREAK(error, 83 /*alloc fail*/);
|
|
|
|
|
CERROR_BREAK(error, 83 /*alloc fail*/)
|
|
|
|
|
|
|
|
|
|
decoded.data[length] = 0;
|
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
@ -4960,18 +4957,18 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, LodePNG
|
|
|
|
|
|
|
|
|
|
/*error: size of the in buffer too small to contain next chunk*/
|
|
|
|
|
if ((size_t)((chunk - in) + 12) > insize || chunk < in)
|
|
|
|
|
CERROR_BREAK(state->error, 30);
|
|
|
|
|
CERROR_BREAK(state->error, 30)
|
|
|
|
|
|
|
|
|
|
/*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
|
|
|
|
|
chunkLength = lodepng_chunk_length(chunk);
|
|
|
|
|
/*error: chunk length larger than the max PNG chunk size*/
|
|
|
|
|
if (chunkLength > 2147483647)
|
|
|
|
|
CERROR_BREAK(state->error, 63);
|
|
|
|
|
CERROR_BREAK(state->error, 63)
|
|
|
|
|
|
|
|
|
|
if ((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in)
|
|
|
|
|
{
|
|
|
|
|
CERROR_BREAK(state->error,
|
|
|
|
|
64); /*error: size of the in buffer too small to contain next chunk*/
|
|
|
|
|
64) /*error: size of the in buffer too small to contain next chunk*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = lodepng_chunk_data_const(chunk);
|
|
|
|
@ -4981,7 +4978,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, LodePNG
|
|
|
|
|
{
|
|
|
|
|
size_t oldsize = idat.size;
|
|
|
|
|
if (!ucvector_resize(&idat, oldsize + chunkLength))
|
|
|
|
|
CERROR_BREAK(state->error, 83 /*alloc fail*/);
|
|
|
|
|
CERROR_BREAK(state->error, 83 /*alloc fail*/)
|
|
|
|
|
for (i = 0; i < chunkLength; i++)
|
|
|
|
|
idat.data[oldsize + i] = data[i];
|
|
|
|
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
|
|
|
@ -5067,7 +5064,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, LodePNG
|
|
|
|
|
{
|
|
|
|
|
/*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
|
|
|
|
|
if (!lodepng_chunk_ancillary(chunk))
|
|
|
|
|
CERROR_BREAK(state->error, 69);
|
|
|
|
|
CERROR_BREAK(state->error, 69)
|
|
|
|
|
|
|
|
|
|
unknown = 1;
|
|
|
|
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
|
|
|
@ -5086,7 +5083,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, LodePNG
|
|
|
|
|
!unknown) /*check CRC if wanted, only on known chunk types*/
|
|
|
|
|
{
|
|
|
|
|
if (lodepng_chunk_check_crc(chunk))
|
|
|
|
|
CERROR_BREAK(state->error, 57); /*invalid CRC*/
|
|
|
|
|
CERROR_BREAK(state->error, 57) /*invalid CRC*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IEND)
|
|
|
|
@ -6095,7 +6092,7 @@ static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const
|
|
|
|
|
unsigned char* padded = (unsigned char*)calloc(
|
|
|
|
|
padded_passstart[i + 1] - padded_passstart[i], sizeof(unsigned char));
|
|
|
|
|
if (!padded)
|
|
|
|
|
ERROR_BREAK(83); /*alloc fail*/
|
|
|
|
|
ERROR_BREAK(83) /*alloc fail*/
|
|
|
|
|
addPaddingBits(padded, &adam7[passstart[i]],
|
|
|
|
|
((passw[i] * bpp + 7ULL) / 8ULL) * 8ULL, passw[i] * bpp * 1ULL,
|
|
|
|
|
passh[i] * 1ULL);
|
|
|
|
|