@@ -129,14 +129,25 @@ static int32_t col_hash_collision_count(const uint8_t* rgb, const uint8_t* hashT
129129/* initialize hash table storing colors and their frequency */
130130static colHashTable * init_col_hash_table (uint32_t tableSize ){
131131 colHashTable * colhash = malloc (sizeof (colHashTable ));
132+ if (colhash == NULL ) return NULL ;
132133 colhash -> tableSize = getNextPrimePower2 (tableSize ); // increase table size to next prime number
133- colhash -> frequ = malloc (sizeof (uint32_t ) * colhash -> tableSize );
134+ colhash -> frequ = malloc (sizeof (uint32_t ) * colhash -> tableSize );
134135 colhash -> hashTable = malloc (3 * colhash -> tableSize );
135136 colhash -> indexUsed = malloc (colhash -> tableSize );
136- colhash -> pPalette = malloc (3 * colhash -> tableSize );
137- colhash -> colIdx = malloc (sizeof (uint32_t )* colhash -> tableSize );
137+ colhash -> pPalette = malloc (3 * colhash -> tableSize );
138+ colhash -> colIdx = malloc (sizeof (uint32_t ) * colhash -> tableSize );
139+ if (colhash -> frequ == NULL || colhash -> hashTable == NULL || colhash -> indexUsed == NULL ||
140+ colhash -> pPalette == NULL || colhash -> colIdx == NULL ) {
141+ free (colhash -> frequ );
142+ free (colhash -> hashTable );
143+ free (colhash -> indexUsed );
144+ free (colhash -> pPalette );
145+ free (colhash -> colIdx );
146+ free (colhash );
147+ return NULL ;
148+ }
138149 colhash -> cnt = 0 ; // no colors initially
139- memset (colhash -> pPalette , 0 , 3 * colhash -> tableSize ); // unused part of color table is uninitialized otheriwse
150+ memset (colhash -> pPalette , 0 , 3 * colhash -> tableSize ); // unused part of color table is uninitialized otherwise
140151 memset (colhash -> indexUsed , 0 , colhash -> tableSize ); // initially no entry in hash-table is used
141152 return colhash ;
142153}
@@ -154,12 +165,25 @@ static void free_col_hash_table(colHashTable* colhash){
154165/* increase the size of the color hash table */
155166static void resize_col_hash_table (colHashTable * colhash ){
156167 uint32_t tableSizeNew ;
157- tableSizeNew = getNextPrimePower2 (colhash -> tableSize ); // increase table size to the next prime number above the next power of two
158- colhash -> pPalette = realloc (colhash -> pPalette , 3 * tableSizeNew );
159- colhash -> colIdx = realloc (colhash -> colIdx , sizeof (uint32_t ) * tableSizeNew );
160- uint8_t * hashTable_new = malloc (3 * tableSizeNew );
161- uint8_t * indexUsed_new = malloc (tableSizeNew );
162- uint32_t * frequ_new = malloc (sizeof (uint32_t ) * tableSizeNew );
168+ tableSizeNew = getNextPrimePower2 (colhash -> tableSize ); // increase table size to the next prime number above the next power of two
169+ uint8_t * pPalette_new = realloc (colhash -> pPalette , 3 * tableSizeNew );
170+ uint32_t * colIdx_new = realloc (colhash -> colIdx , sizeof (uint32_t ) * tableSizeNew );
171+ uint8_t * hashTable_new = malloc (3 * tableSizeNew );
172+ uint8_t * indexUsed_new = malloc (tableSizeNew );
173+ uint32_t * frequ_new = malloc (sizeof (uint32_t ) * tableSizeNew );
174+ if (pPalette_new == NULL || colIdx_new == NULL || hashTable_new == NULL ||
175+ indexUsed_new == NULL || frequ_new == NULL ) {
176+ // realloc failure: original pointers may be freed or unchanged; clean up and leave colhash intact
177+ free (hashTable_new );
178+ free (indexUsed_new );
179+ free (frequ_new );
180+ // if realloc returned NULL, original pointer is still valid
181+ if (pPalette_new != NULL ) colhash -> pPalette = pPalette_new ;
182+ if (colIdx_new != NULL ) colhash -> colIdx = colIdx_new ;
183+ return ;
184+ }
185+ colhash -> pPalette = pPalette_new ;
186+ colhash -> colIdx = colIdx_new ;
163187 memset (indexUsed_new , 0 , tableSizeNew );
164188 colhash -> cnt = 0 ;
165189 for (uint32_t j = 0 ; j < colhash -> tableSize ; ++ j ) { // TBD (no improvement when tested): easier to loop over pPalette and also leave pPalette in place?, if indexUsed is also unnecessary then
@@ -176,15 +200,16 @@ static void resize_col_hash_table(colHashTable* colhash){
176200 colhash -> tableSize = tableSizeNew ;
177201 free (colhash -> hashTable ); // free part of old hash table that is not used anymore
178202 free (colhash -> indexUsed ); // free part of old hash table that is not used anymore
179- free (colhash -> frequ ); // free part of old hash table that is not used anymore
203+ free (colhash -> frequ ); // free part of old hash table that is not used anymore
180204 colhash -> hashTable = hashTable_new ; // pass pointer to new hash table
181205 colhash -> indexUsed = indexUsed_new ; // pass pointer to new hash table
182- colhash -> frequ = frequ_new ; // pass pointer to new hash table
206+ colhash -> frequ = frequ_new ; // pass pointer to new hash table
183207}
184208
185209/* take frequ indexed by hash(rgb) and return corresponding dense array */
186210static uint32_t * hash_to_dense (colHashTable * colhash , cgif_chan_fmt fmtChan ) {
187211 uint32_t * frequDense = malloc (sizeof (uint32_t ) * colhash -> cnt );
212+ if (frequDense == NULL ) return NULL ;
188213 uint32_t h ;
189214 (void )fmtChan ;
190215 for (uint32_t i = 0 ; i < colhash -> cnt ; ++ i ) {
@@ -243,6 +268,7 @@ static treeNode* new_tree_node(uint8_t* pPalette, uint32_t* frequ, uint16_t* num
243268 float var [3 ];
244269
245270 treeNode * node = malloc (sizeof (treeNode ));
271+ if (node == NULL ) return NULL ;
246272 node -> idxMin = idxMin ; // minimum color in pPalette belonging to the node
247273 node -> idxMax = idxMax ; // maximum color in pPalette belonging to the node
248274 get_variance (pPalette , frequ , idxMin , idxMax , var , node -> mean );
@@ -488,10 +514,18 @@ static uint32_t quantize_and_dither(colHashTable* colhash, const uint8_t* pImage
488514 const uint16_t colMax = (1uL << depthMax ) - 1 ; // maximum number of colors (-1 to leave space for transparency), disadvantage (TBD): quantization for static image with 256 colors and no alpha channel unnecessary
489515 if (colhash -> cnt > colMax ) { // color-quantization is needed
490516 uint32_t * pFrequDense = hash_to_dense (colhash , fmtChan );
517+ if (pFrequDense == NULL ) return 0 ;
491518 treeNode * root = create_decision_tree (colhash -> pPalette , pFrequDense , pPalette256 , colhash -> cnt , colMax , depthMax ); // create decision tree (dynamic, splits along rgb-dimension with highest variance)
492519 free (pFrequDense );
493- float * pImageDataRGBfloat = malloc (fmtChan * numPixel * sizeof (float )); // TBD fmtChan + only when hasAlpha
494- for (uint32_t i = 0 ; i < fmtChan * numPixel ; ++ i ){
520+ if (root == NULL ) return 0 ;
521+ // Guard against integer overflow: fmtChan (uint8_t) * numPixel (uint32_t) can overflow uint32_t
522+ size_t floatBufSize = (size_t )fmtChan * (size_t )numPixel * sizeof (float );
523+ float * pImageDataRGBfloat = malloc (floatBufSize );
524+ if (pImageDataRGBfloat == NULL ) {
525+ free_decision_tree (root );
526+ return 0 ;
527+ }
528+ for (uint32_t i = 0 ; i < (size_t )fmtChan * numPixel ; ++ i ){
495529 pImageDataRGBfloat [i ] = pImageDataRGB [i ];
496530 }
497531 uint8_t transIndex = colMax ;
@@ -519,8 +553,9 @@ static uint32_t quantize_and_dither(colHashTable* colhash, const uint8_t* pImage
519553CGIFrgb * cgif_rgb_newgif (const CGIFrgb_Config * pConfig ) {
520554 CGIF_Config idxConfig = {0 };
521555 CGIFrgb * pGIFrgb ;
522-
556+
523557 pGIFrgb = malloc (sizeof (CGIFrgb ));
558+ if (pGIFrgb == NULL ) return NULL ;
524559 memset (pGIFrgb , 0 , sizeof (CGIFrgb ));
525560 idxConfig .pWriteFn = pConfig -> pWriteFn ;
526561 idxConfig .pContext = pConfig -> pContext ;
@@ -536,7 +571,7 @@ CGIFrgb* cgif_rgb_newgif(const CGIFrgb_Config* pConfig) {
536571 }
537572 pGIFrgb -> config = * pConfig ;
538573 pGIFrgb -> curResult = CGIF_PENDING ;
539- return pGIFrgb ;
574+ return pGIFrgb ;
540575}
541576
542577cgif_result cgif_rgb_addframe (CGIFrgb * pGIF , const CGIFrgb_FrameConfig * pConfig ) {
@@ -558,9 +593,18 @@ cgif_result cgif_rgb_addframe(CGIFrgb* pGIF, const CGIFrgb_FrameConfig* pConfig)
558593 return CGIF_ERROR ;
559594 }
560595 pNewBef = malloc (pConfig -> fmtChan * MULU16 (imageWidth , imageHeight ));
596+ if (pNewBef == NULL ) {
597+ pGIF -> curResult = CGIF_ERROR ;
598+ return CGIF_ERROR ;
599+ }
561600 memcpy (pNewBef , pConfig -> pImageData , pConfig -> fmtChan * MULU16 (imageWidth , imageHeight ));
562601 fConfig .pLocalPalette = aPalette ;
563602 fConfig .pImageData = malloc (pGIF -> config .width * (uint32_t )pGIF -> config .height );
603+ if (fConfig .pImageData == NULL ) {
604+ free (pNewBef );
605+ pGIF -> curResult = CGIF_ERROR ;
606+ return CGIF_ERROR ;
607+ }
564608 fConfig .delay = pConfig -> delay ;
565609 fConfig .attrFlags = CGIF_FRAME_ATTR_USE_LOCAL_TABLE ;
566610 if (pConfig -> attrFlags & CGIF_RGB_FRAME_ATTR_INTERLACED ) {
0 commit comments