@@ -385,6 +385,7 @@ void PNGAPI
385385png_set_hIST (png_const_structrp png_ptr , png_inforp info_ptr ,
386386 png_const_uint_16p hist )
387387{
388+ png_uint_16 safe_hist [PNG_MAX_PALETTE_LENGTH ];
388389 int i ;
389390
390391 png_debug1 (1 , "in %s storage function" , "hIST" );
@@ -401,6 +402,13 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
401402 return ;
402403 }
403404
405+ /* Snapshot the caller's hist before freeing, in case it points to
406+ * info_ptr->hist (getter-to-setter aliasing).
407+ */
408+ memcpy (safe_hist , hist , (unsigned int )info_ptr -> num_palette *
409+ (sizeof (png_uint_16 )));
410+ hist = safe_hist ;
411+
404412 png_free_data (png_ptr , info_ptr , PNG_FREE_HIST , 0 );
405413
406414 /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
@@ -742,7 +750,7 @@ void PNGAPI
742750png_set_PLTE (png_structrp png_ptr , png_inforp info_ptr ,
743751 png_const_colorp palette , int num_palette )
744752{
745-
753+ png_color safe_palette [ PNG_MAX_PALETTE_LENGTH ];
746754 png_uint_32 max_palette_length ;
747755
748756 png_debug1 (1 , "in %s storage function" , "PLTE" );
@@ -776,6 +784,15 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
776784 png_error (png_ptr , "Invalid palette" );
777785 }
778786
787+ /* Snapshot the caller's palette before freeing, in case it points to
788+ * info_ptr->palette (getter-to-setter aliasing).
789+ */
790+ if (num_palette > 0 )
791+ memcpy (safe_palette , palette , (unsigned int )num_palette *
792+ (sizeof (png_color )));
793+
794+ palette = safe_palette ;
795+
779796 png_free_data (png_ptr , info_ptr , PNG_FREE_PLTE , 0 );
780797
781798 /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
@@ -937,6 +954,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
937954 png_const_textp text_ptr , int num_text )
938955{
939956 int i ;
957+ png_textp old_text = NULL ;
940958
941959 png_debug1 (1 , "in text storage function, chunk typeid = 0x%lx" ,
942960 png_ptr == NULL ? 0xabadca11UL : (unsigned long )png_ptr -> chunk_name );
@@ -984,7 +1002,10 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
9841002 return 1 ;
9851003 }
9861004
987- png_free (png_ptr , info_ptr -> text );
1005+ /* Defer freeing the old array until after the copy loop below,
1006+ * in case text_ptr aliases info_ptr->text (getter-to-setter).
1007+ */
1008+ old_text = info_ptr -> text ;
9881009
9891010 info_ptr -> text = new_text ;
9901011 info_ptr -> free_me |= PNG_FREE_TEXT ;
@@ -1069,6 +1090,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
10691090 {
10701091 png_chunk_report (png_ptr , "text chunk: out of memory" ,
10711092 PNG_CHUNK_WRITE_ERROR );
1093+ png_free (png_ptr , old_text );
10721094
10731095 return 1 ;
10741096 }
@@ -1122,6 +1144,8 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
11221144 png_debug1 (3 , "transferred text chunk %d" , info_ptr -> num_text );
11231145 }
11241146
1147+ png_free (png_ptr , old_text );
1148+
11251149 return 0 ;
11261150}
11271151#endif
@@ -1165,6 +1189,16 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
11651189
11661190 if (trans_alpha != NULL )
11671191 {
1192+ /* Snapshot the caller's trans_alpha before freeing, in case it
1193+ * points to info_ptr->trans_alpha (getter-to-setter aliasing).
1194+ */
1195+ png_byte safe_trans [PNG_MAX_PALETTE_LENGTH ];
1196+
1197+ if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH )
1198+ memcpy (safe_trans , trans_alpha , (size_t )num_trans );
1199+
1200+ trans_alpha = safe_trans ;
1201+
11681202 png_free_data (png_ptr , info_ptr , PNG_FREE_TRNS , 0 );
11691203
11701204 if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH )
@@ -1249,6 +1283,7 @@ png_set_sPLT(png_const_structrp png_ptr,
12491283 */
12501284{
12511285 png_sPLT_tp np ;
1286+ png_sPLT_tp old_spalettes ;
12521287
12531288 png_debug1 (1 , "in %s storage function" , "sPLT" );
12541289
@@ -1269,7 +1304,10 @@ png_set_sPLT(png_const_structrp png_ptr,
12691304 return ;
12701305 }
12711306
1272- png_free (png_ptr , info_ptr -> splt_palettes );
1307+ /* Defer freeing the old array until after the copy loop below,
1308+ * in case entries aliases info_ptr->splt_palettes (getter-to-setter).
1309+ */
1310+ old_spalettes = info_ptr -> splt_palettes ;
12731311
12741312 info_ptr -> splt_palettes = np ;
12751313 info_ptr -> free_me |= PNG_FREE_SPLT ;
@@ -1333,6 +1371,8 @@ png_set_sPLT(png_const_structrp png_ptr,
13331371 }
13341372 while (-- nentries );
13351373
1374+ png_free (png_ptr , old_spalettes );
1375+
13361376 if (nentries > 0 )
13371377 png_chunk_report (png_ptr , "sPLT out of memory" , PNG_CHUNK_WRITE_ERROR );
13381378}
@@ -1381,6 +1421,7 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
13811421 png_inforp info_ptr , png_const_unknown_chunkp unknowns , int num_unknowns )
13821422{
13831423 png_unknown_chunkp np ;
1424+ png_unknown_chunkp old_unknowns ;
13841425
13851426 if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
13861427 unknowns == NULL )
@@ -1427,7 +1468,10 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
14271468 return ;
14281469 }
14291470
1430- png_free (png_ptr , info_ptr -> unknown_chunks );
1471+ /* Defer freeing the old array until after the copy loop below,
1472+ * in case unknowns aliases info_ptr->unknown_chunks (getter-to-setter).
1473+ */
1474+ old_unknowns = info_ptr -> unknown_chunks ;
14311475
14321476 info_ptr -> unknown_chunks = np ; /* safe because it is initialized */
14331477 info_ptr -> free_me |= PNG_FREE_UNKN ;
@@ -1473,6 +1517,8 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
14731517 ++ np ;
14741518 ++ (info_ptr -> unknown_chunks_num );
14751519 }
1520+
1521+ png_free (png_ptr , old_unknowns );
14761522}
14771523
14781524void PNGAPI
0 commit comments