Skip to content

Commit 77300dc

Browse files
authored
Merge branch 'main' into fix/lzw-allocation-overflow-guard
2 parents 07bf827 + f1272ac commit 77300dc

6 files changed

Lines changed: 290 additions & 52 deletions

File tree

.github/workflows/cifuzz.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
sanitizer: ${{ matrix.sanitizer }}
2424
fuzz-seconds: 600
2525
- name: Upload Crash
26-
uses: actions/upload-artifact@v6
26+
uses: actions/upload-artifact@v7
2727
if: failure() && steps.build.outcome == 'success'
2828
with:
2929
name: artifacts

src/cgif.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ static void copyFrameConfig(CGIF_FrameConfig* pDest, CGIF_FrameConfig* pSrc) {
480480
int cgif_addframe(CGIF* pGIF, CGIF_FrameConfig* pConfig) {
481481
CGIF_Frame* pNewFrame;
482482
int hasAlpha, hasSetTransp;
483-
int i;
483+
uint32_t i;
484484
cgif_result r;
485485

486486
// check for previous errors
@@ -518,7 +518,7 @@ int cgif_addframe(CGIF* pGIF, CGIF_FrameConfig* pConfig) {
518518
sameFrame = 0;
519519
}
520520
} else {
521-
for(i = 0; i < pGIF->config.width * pGIF->config.height; i++) {
521+
for(i = 0; i < MULU16(pGIF->config.width, pGIF->config.height); i++) {
522522
if(cmpPixel(pGIF, pConfig, &pGIF->aFrames[pGIF->iHEAD]->config, pConfig->pImageData[i], pGIF->aFrames[pGIF->iHEAD]->config.pImageData[i])) {
523523
sameFrame = 0;
524524
break;

src/cgif_raw.c

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ typedef struct {
4242

4343
typedef struct {
4444
uint16_t* pTreeInit; // LZW dictionary tree for the initial dictionary (0-255 max)
45-
uint16_t* pTreeList; // LZW dictionary tree as list (max. number of children per node = 1)
45+
uint16_t* pTreeListMap; // LZW tree list: mapPos per node
46+
uint8_t* pTreeListColor; // LZW tree list: child color per node
47+
uint16_t* pTreeListIdx; // LZW tree list: child LZW index per node
4648
uint16_t* pTreeMap; // LZW dictionary tree as map (backup to pTreeList in case more than 1 child is present)
4749
uint16_t* pLZWData; // pointer to LZW data
4850
const uint8_t* pImageData; // pointer to image data
@@ -92,27 +94,27 @@ static void resetDict(LZWGenState* pContext, const uint16_t initDictLen) {
9294
++(pContext->LZWPos); // increment position in LZW data
9395
// reset LZW list
9496
memset(pContext->pTreeInit, 0, initDictLen * sizeof(uint16_t) * initDictLen);
95-
memset(pContext->pTreeList, 0, ((sizeof(uint16_t) * 2) + sizeof(uint16_t)) * MAX_DICT_LEN);
97+
memset(pContext->pTreeListMap, 0, sizeof(uint16_t) * MAX_DICT_LEN);
98+
memset(pContext->pTreeListColor, 0, sizeof(uint8_t) * MAX_DICT_LEN);
99+
memset(pContext->pTreeListIdx, 0, sizeof(uint16_t) * MAX_DICT_LEN);
96100
}
97101

98102
/* add new child node */
99103
static void add_child(LZWGenState* pContext, const uint16_t parentIndex, const uint16_t LZWIndex, const uint16_t initDictLen, const uint8_t nextColor) {
100-
uint16_t* pTreeList;
101-
uint16_t mapPos;
104+
uint16_t mapPos;
102105

103-
pTreeList = pContext->pTreeList;
104-
mapPos = pTreeList[parentIndex * (2 + 1)];
106+
mapPos = pContext->pTreeListMap[parentIndex];
105107
if(!mapPos) { // if pTreeMap is not used yet for the parent node
106-
if(pTreeList[parentIndex * (2 + 1) + 2]) { // if at least one child node exists, switch to pTreeMap
108+
if(pContext->pTreeListIdx[parentIndex]) { // if at least one child node exists, switch to pTreeMap
107109
mapPos = pContext->mapPos;
108110
// add child to mapping table (pTreeMap)
109111
memset(pContext->pTreeMap + ((mapPos - 1) * initDictLen), 0, initDictLen * sizeof(uint16_t));
110112
pContext->pTreeMap[(mapPos - 1) * initDictLen + nextColor] = LZWIndex;
111-
pTreeList[parentIndex * (2 + 1)] = mapPos;
113+
pContext->pTreeListMap[parentIndex] = mapPos;
112114
++(pContext->mapPos);
113115
} else { // use the free spot in pTreeList for the child node
114-
pTreeList[parentIndex * (2 + 1) + 1] = nextColor; // color that leads to child node
115-
pTreeList[parentIndex * (2 + 1) + 2] = LZWIndex; // position of child node
116+
pContext->pTreeListColor[parentIndex] = nextColor; // color that leads to child node
117+
pContext->pTreeListIdx[parentIndex] = LZWIndex; // position of child node
116118
}
117119
} else { // directly add child node to pTreeMap
118120
pContext->pTreeMap[(mapPos - 1) * initDictLen + nextColor] = LZWIndex;
@@ -123,7 +125,6 @@ static void add_child(LZWGenState* pContext, const uint16_t parentIndex, const u
123125
/* find next LZW code representing the longest pixel sequence that is still in the dictionary*/
124126
static int lzw_crawl_tree(LZWGenState* pContext, uint32_t* pStrPos, uint16_t parentIndex, const uint16_t initDictLen) {
125127
uint16_t* pTreeInit;
126-
uint16_t* pTreeList;
127128
uint32_t strPos;
128129
uint16_t nextParent;
129130
uint16_t mapPos;
@@ -132,7 +133,6 @@ static int lzw_crawl_tree(LZWGenState* pContext, uint32_t* pStrPos, uint16_t par
132133
return CGIF_EINDEX; // error: index in image data out-of-bounds
133134
}
134135
pTreeInit = pContext->pTreeInit;
135-
pTreeList = pContext->pTreeList;
136136
strPos = *pStrPos;
137137
// get the next LZW code from pTreeInit:
138138
// the initial nodes (0-255 max) have more children on average.
@@ -165,13 +165,13 @@ static int lzw_crawl_tree(LZWGenState* pContext, uint32_t* pStrPos, uint16_t par
165165
return CGIF_EINDEX; // error: index in image data out-of-bounds
166166
}
167167
// first try to find child in LZW list
168-
if(pTreeList[parentIndex * (2 + 1) + 2] && pTreeList[parentIndex * (2 + 1) + 1] == pContext->pImageData[strPos + 1]) {
169-
parentIndex = pTreeList[parentIndex * (2 + 1) + 2];
168+
if(pContext->pTreeListIdx[parentIndex] && pContext->pTreeListColor[parentIndex] == pContext->pImageData[strPos + 1]) {
169+
parentIndex = pContext->pTreeListIdx[parentIndex];
170170
++strPos;
171171
continue;
172172
}
173173
// not found child yet? try to look into the LZW mapping table
174-
mapPos = pContext->pTreeList[parentIndex * (2 + 1)];
174+
mapPos = pContext->pTreeListMap[parentIndex];
175175
if(mapPos) {
176176
nextParent = pContext->pTreeMap[(mapPos - 1) * initDictLen + pContext->pImageData[strPos + 1]];
177177
if(nextParent) {
@@ -314,8 +314,10 @@ static int LZW_GenerateStream(LZWResult* pResult, const uint32_t numPixel, const
314314
r = CGIF_EALLOC;
315315
goto LZWGENERATE_Cleanup;
316316
}
317-
pContext->pTreeList = malloc(((sizeof(uint16_t) * 2) + sizeof(uint16_t)) * MAX_DICT_LEN);
318-
if(pContext->pTreeList == NULL) {
317+
pContext->pTreeListMap = malloc(sizeof(uint16_t) * MAX_DICT_LEN);
318+
pContext->pTreeListColor = malloc(sizeof(uint8_t) * MAX_DICT_LEN);
319+
pContext->pTreeListIdx = malloc(sizeof(uint16_t) * MAX_DICT_LEN);
320+
if(pContext->pTreeListMap == NULL || pContext->pTreeListColor == NULL || pContext->pTreeListIdx == NULL) {
319321
r = CGIF_EALLOC;
320322
goto LZWGENERATE_Cleanup;
321323
}
@@ -377,7 +379,9 @@ static int LZW_GenerateStream(LZWResult* pResult, const uint32_t numPixel, const
377379
LZWGENERATE_Cleanup:
378380
free(pContext->pLZWData);
379381
free(pContext->pTreeInit);
380-
free(pContext->pTreeList);
382+
free(pContext->pTreeListMap);
383+
free(pContext->pTreeListColor);
384+
free(pContext->pTreeListIdx);
381385
free(pContext->pTreeMap);
382386
free(pContext);
383387
return r;

0 commit comments

Comments
 (0)