fix: Prevent double-freeing `png_struct` members on allocation failure

Clear the pointers inside `png_struct` after `png_free`, following the
existing idiom in `png_read_buffer`, to ensure that a subsequent free
will be a no-op.

Several read-side functions free a `png_struct` member and allocate
a replacement without clearing the pointer in between. When that
allocation fails, `png_malloc` calls `png_error`, which longjmps out
before the assignment, leaving the member pointing at freed memory.
The application's cleanup path (`png_destroy_read_struct`, then
`png_read_destroy`) then frees it a second time.

The same defect occurs at five members across four functions:
 - `big_row_buf` and `big_prev_row` in `png_read_start_row`;
 - `palette` in `png_set_PLTE`;
 - `trans_alpha` in `png_set_tRNS`;
 - `quantize_index` in `png_set_quantize`.

This is robustness hardening, not a fix for untrusted input. Arming
the double-free needs a prior successful pass through the same site,
and PNG content alone cannot deliver one: duplicate PLTE and tRNS
chunks are rejected before their setters run, and, although APNG
re-runs `png_read_start_row` on every frame, fcTL validation caps
each frame to the first frame's dimensions, so the row-buffer
reallocation guard cannot re-fire within one decode.

The trigger is an application that causes a setter to run twice on one
`png_struct` or reuses the struct across decodes, and then meets an
allocation failure.

Co-authored-by: Cosmin Truta <ctruta@gmail.com>
Signed-off-by: Anthony Hurtado <amhurtado@pm.me>
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
diff --git a/AUTHORS.md b/AUTHORS.md
index 291a0b7..be1c9b6 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -7,6 +7,7 @@
  * Adam Richter
  * Alexander Smorkalov
  * Andreas Dilger
+ * Anthony Hurtado
  * Chris Blume
  * Cosmin Truta
  * Daisuke Nishikawa
diff --git a/pngrtran.c b/pngrtran.c
index 25a333f..38a9fb9 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -495,6 +495,7 @@
        * this function more than once per png_struct.
        */
       png_free(png_ptr, png_ptr->quantize_index);
+      png_ptr->quantize_index = NULL;
       png_ptr->quantize_index = (png_byte *)png_malloc(png_ptr,
           PNG_MAX_PALETTE_LENGTH);
       for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
diff --git a/pngrutil.c b/pngrutil.c
index 6d937c8..d426075 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -4790,6 +4790,7 @@
    {
       png_free(png_ptr, png_ptr->big_row_buf);
       png_free(png_ptr, png_ptr->big_prev_row);
+      png_ptr->big_row_buf = png_ptr->big_prev_row = NULL;
 
       if (png_ptr->interlaced != 0)
          png_ptr->big_row_buf = (png_byte *)png_calloc(png_ptr,
diff --git a/pngset.c b/pngset.c
index 773a2f8..10eea62 100644
--- a/pngset.c
+++ b/pngset.c
@@ -809,6 +809,7 @@
     * regardless of num_palette.
     */
    png_free(png_ptr, png_ptr->palette);
+   png_ptr->palette = NULL;
    png_ptr->palette = png_voidcast(png_color *, png_calloc(png_ptr,
        PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
    info_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
@@ -1221,6 +1222,7 @@
            * functions (e.g. png_do_expand_palette).
            */
           png_free(png_ptr, png_ptr->trans_alpha);
+          png_ptr->trans_alpha = NULL;
           png_ptr->trans_alpha = png_voidcast(png_bytep,
               png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
           memset(png_ptr->trans_alpha, 0xff, PNG_MAX_PALETTE_LENGTH);