Index: libpng-1.2.59/Makefile.am
===================================================================
--- libpng-1.2.59.orig/Makefile.am
+++ libpng-1.2.59/Makefile.am
@@ -14,12 +14,14 @@ PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PN
 AUTOMAKE_OPTIONS = foreign
 
 # test programs - run on make check, make distcheck
-check_PROGRAMS= pngtest cve-2026-33416
+check_PROGRAMS= pngtest cve-2026-33416 cve-2026-34757
 pngtest_SOURCES = pngtest.c
 pngtest_LDADD = libpng12.la
 cve_2026_33416_SOURCES = cve-2026-33416.c
 cve_2026_33416_LDADD = libpng12.la
-TESTS = test-pngtest.sh cve-2026-33416
+cve_2026_34757_SOURCES = cve-2026-34757.c
+cve_2026_34757_LDADD = libpng12.la
+TESTS = test-pngtest.sh cve-2026-33416 cve-2026-34757
 TESTS_ENVIRONMENT= srcdir=$(srcdir)
 
 # man pages
@@ -92,6 +94,7 @@ EXTRA_DIST= \
 	${srcdir}/contrib/visupng/* \
 	$(TESTS) \
 	cve-2026-33416.c \
+	cve-2026-34757.c \
 	example.c libpng-1.2.59.txt pnggccrd.c pngvcrd.c
 
 CLEANFILES= pngout.png libpng12.pc libpng12-config libpng.vers \
Index: libpng-1.2.59/pngset.c
===================================================================
--- libpng-1.2.59.orig/pngset.c
+++ libpng-1.2.59/pngset.c
@@ -182,6 +182,7 @@ png_set_gAMA_fixed(png_structp png_ptr,
 void PNGAPI
 png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
 {
+   png_uint_16 safe_hist[PNG_MAX_PALETTE_LENGTH];
    int i;
 
    png_debug1(1, "in %s storage function", "hIST");
@@ -197,6 +198,13 @@ png_set_hIST(png_structp png_ptr, png_in
       return;
    }
 
+   /* Snapshot the caller's hist before freeing, in case it points to
+    * info_ptr->hist (getter-to-setter aliasing).
+    */
+   png_memcpy(safe_hist, hist, (unsigned int)info_ptr->num_palette *
+       (png_sizeof(png_uint_16)));
+   hist = safe_hist;
+
 #ifdef PNG_FREE_ME_SUPPORTED
    png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
 #endif
@@ -460,7 +468,7 @@ void PNGAPI
 png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
    png_colorp palette, int num_palette)
 {
-
+   png_color safe_palette[PNG_MAX_PALETTE_LENGTH];
    png_uint_32 max_palette_length;
 
    png_debug1(1, "in %s storage function", "PLTE");
@@ -482,6 +490,15 @@ png_set_PLTE(png_structp png_ptr, png_in
       }
    }
 
+   /* Snapshot the caller's palette before freeing, in case it points to
+    * info_ptr->palette (getter-to-setter aliasing).
+    */
+   if (num_palette > 0)
+      png_memcpy(safe_palette, palette, (unsigned int)num_palette *
+          (png_sizeof(png_color)));
+
+   palette = safe_palette;
+
    /* It may not actually be necessary to set png_ptr->palette here;
     * we do it for backward compatibility with the way the png_handle_tRNS
     * function used to do the allocation.
@@ -680,6 +697,7 @@ png_set_text_2(png_structp png_ptr, png_
                int num_text)
 {
    int i;
+   png_textp old_text = NULL;
 
    png_debug1(1, "in %s storage function", ((png_ptr == NULL ||
       png_ptr->chunk_name[0] == '\0') ?
@@ -709,8 +727,6 @@ png_set_text_2(png_structp png_ptr, png_
 
       if (info_ptr->text != NULL)
       {
-         png_textp old_text;
-
          info_ptr->max_text = info_ptr->num_text + num_text + 8;
          old_text = info_ptr->text;
 
@@ -725,7 +741,6 @@ png_set_text_2(png_structp png_ptr, png_
          }
          png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
             png_sizeof(png_text)));
-         png_free(png_ptr, old_text);
       }
       else
       {
@@ -807,7 +822,10 @@ png_set_text_2(png_structp png_ptr, png_
          (png_uint_32)
          (key_len + text_length + lang_len + lang_key_len + 4));
       if (textp->key == NULL)
+      {
+         png_free(png_ptr, old_text);
          return(1);
+      }
       png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
                  (png_uint_32)
                  (key_len + lang_len + lang_key_len + text_length + 4),
@@ -858,6 +876,7 @@ png_set_text_2(png_structp png_ptr, png_
       info_ptr->num_text++;
       png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
    }
+   png_free(png_ptr, old_text);
    return(0);
 }
 #endif
@@ -904,6 +923,16 @@ png_set_tRNS(png_structp png_ptr, png_in
 
    if (trans != NULL)
    {
+       /* Snapshot the caller's trans before freeing, in case it
+        * points to info_ptr->trans (getter-to-setter aliasing).
+        */
+       png_byte safe_trans[PNG_MAX_PALETTE_LENGTH];
+
+       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+          png_memcpy(safe_trans, trans, (png_size_t)num_trans);
+
+       trans = safe_trans;
+
        /* It may not actually be necessary to set png_ptr->trans here;
         * we do it for backward compatibility with the way the png_handle_tRNS
         * function used to do the allocation.
@@ -973,6 +1002,7 @@ png_set_sPLT(png_structp png_ptr,
  */
 {
    png_sPLT_tp np;
+   png_sPLT_tp old_spalettes;
    int i;
 
    if (png_ptr == NULL || info_ptr == NULL)
@@ -999,7 +1029,11 @@ png_set_sPLT(png_structp png_ptr,
 
    png_memcpy(np, info_ptr->splt_palettes,
        info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
-   png_free(png_ptr, info_ptr->splt_palettes);
+
+   /* Defer freeing the old array until after the copy loop below,
+    * in case entries aliases info_ptr->splt_palettes (getter-to-setter).
+    */
+   old_spalettes = info_ptr->splt_palettes;
    info_ptr->splt_palettes=NULL;
 
    for (i = 0; i < nentries; i++)
@@ -1035,6 +1069,7 @@ png_set_sPLT(png_structp png_ptr,
 
    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
+   png_free(png_ptr, old_spalettes);
    info_ptr->valid |= PNG_INFO_sPLT;
 #ifdef PNG_FREE_ME_SUPPORTED
    info_ptr->free_me |= PNG_FREE_SPLT;
@@ -1048,6 +1083,7 @@ png_set_unknown_chunks(png_structp png_p
    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
 {
    png_unknown_chunkp np;
+   png_unknown_chunkp old_unknowns;
    int i;
 
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
@@ -1073,7 +1109,11 @@ png_set_unknown_chunks(png_structp png_p
 
    png_memcpy(np, info_ptr->unknown_chunks,
        info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
-   png_free(png_ptr, info_ptr->unknown_chunks);
+
+   /* Defer freeing the old array until after the copy loop below,
+    * in case unknowns aliases info_ptr->unknown_chunks (getter-to-setter).
+    */
+   old_unknowns = info_ptr->unknown_chunks;
    info_ptr->unknown_chunks = NULL;
 
    for (i = 0; i < num_unknowns; i++)
@@ -1107,6 +1147,7 @@ png_set_unknown_chunks(png_structp png_p
 
    info_ptr->unknown_chunks = np;
    info_ptr->unknown_chunks_num += num_unknowns;
+   png_free(png_ptr, old_unknowns);
 #ifdef PNG_FREE_ME_SUPPORTED
    info_ptr->free_me |= PNG_FREE_UNKN;
 #endif
Index: libpng-1.2.59/cve-2026-34757.c
===================================================================
--- /dev/null
+++ libpng-1.2.59/cve-2026-34757.c
@@ -0,0 +1,372 @@
+/* cve-2026-34757.c
+ *
+ * Copyright (c) 2026 Cosmin Truta
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * Test the get-then-set roundtrip pattern for various chunks.
+ *
+ * Passing the internal pointer returned by a getter back into the
+ * corresponding setter is a natural API usage pattern.  A previous
+ * version had a use-after-free on this path because the setter freed
+ * the internal buffer before copying from the caller-supplied pointer.
+ */
+
+#include "png.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int test_PLTE_aliasing(void) {
+    int i;
+    printf("Testing PLTE aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_color palette[4];
+    for (i = 0; i < 4; i++) {
+        palette[i].red = (png_byte)(i * 10);
+        palette[i].green = (png_byte)(i * 20);
+        palette[i].blue = (png_byte)(i * 30);
+    }
+
+    png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE,
+                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+    png_set_PLTE(png_ptr, info_ptr, palette, 4);
+
+    png_colorp got_palette;
+    int num_palette;
+    png_get_PLTE(png_ptr, info_ptr, &got_palette, &num_palette);
+
+    /* Critical call: got_palette aliases internal info_ptr->palette */
+    png_set_PLTE(png_ptr, info_ptr, got_palette, num_palette);
+
+    /* Verify data */
+    png_get_PLTE(png_ptr, info_ptr, &got_palette, &num_palette);
+    if (num_palette != 4) {
+        fprintf(stderr, "FAIL: PLTE count mismatch\n");
+        goto fail;
+    }
+    for (i = 0; i < 4; i++) {
+        if (got_palette[i].red != (png_byte)(i * 10) ||
+            got_palette[i].green != (png_byte)(i * 20) ||
+            got_palette[i].blue != (png_byte)(i * 30)) {
+            fprintf(stderr, "FAIL: PLTE data corruption at %d\n", i);
+            goto fail;
+        }
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+
+#ifdef PNG_hIST_SUPPORTED
+static int test_hIST_aliasing(void) {
+    int i;
+    printf("Testing hIST aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_color palette[4] = {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}};
+    png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE,
+                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+    png_set_PLTE(png_ptr, info_ptr, palette, 4);
+
+    png_uint_16 hist[4] = {100, 200, 300, 400};
+    png_set_hIST(png_ptr, info_ptr, hist);
+
+    png_uint_16p got_hist;
+    png_get_hIST(png_ptr, info_ptr, &got_hist);
+
+    /* Critical call: got_hist aliases internal info_ptr->hist */
+    png_set_hIST(png_ptr, info_ptr, got_hist);
+
+    /* Verify data */
+    png_get_hIST(png_ptr, info_ptr, &got_hist);
+    for (i = 0; i < 4; i++) {
+        if (got_hist[i] != (png_uint_16)((i + 1) * 100)) {
+            fprintf(stderr, "FAIL: hIST data corruption at %d\n", i);
+            goto fail;
+        }
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+static int test_tRNS_aliasing(void) {
+    printf("Testing tRNS aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_color palette[4] = {{0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}};
+    png_set_IHDR(png_ptr, info_ptr, 1, 1, 8, PNG_COLOR_TYPE_PALETTE,
+                 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+    png_set_PLTE(png_ptr, info_ptr, palette, 4);
+
+    png_byte trans[4] = {255, 128, 64, 0};
+    png_set_tRNS(png_ptr, info_ptr, trans, 4, NULL);
+
+    png_bytep got_trans;
+    int num_trans;
+    png_color_16p trans_values;
+    png_get_tRNS(png_ptr, info_ptr, &got_trans, &num_trans, &trans_values);
+
+    /* Critical call: got_trans aliases internal info_ptr->trans */
+    png_set_tRNS(png_ptr, info_ptr, got_trans, num_trans, trans_values);
+
+    /* Verify data */
+    png_get_tRNS(png_ptr, info_ptr, &got_trans, &num_trans, &trans_values);
+    if (num_trans != 4) {
+        fprintf(stderr, "FAIL: tRNS count mismatch\n");
+        goto fail;
+    }
+    if (got_trans[1] != 128 || got_trans[2] != 64 || got_trans[3] != 0) {
+        fprintf(stderr, "FAIL: tRNS data corruption\n");
+        goto fail;
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED
+static int test_text_aliasing(void) {
+    printf("Testing text aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_text text[2];
+    text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+    text[0].key = (png_charp)"Key1";
+    text[0].text = (png_charp)"Value1";
+    text[1].compression = PNG_TEXT_COMPRESSION_NONE;
+    text[1].key = (png_charp)"Key2";
+    text[1].text = (png_charp)"Value2";
+
+    png_set_text(png_ptr, info_ptr, text, 2);
+
+    png_textp got_text;
+    int num_text;
+    png_get_text(png_ptr, info_ptr, &got_text, &num_text);
+
+    /* Trigger reallocation by adding enough entries to exceed max_text (initially 0+2+8=10, so let's add 10 more) */
+    /* This will use the deferred free path in png_set_text_2 */
+    {
+        int i;
+        for (i = 0; i < 5; i++) {
+            png_set_text(png_ptr, info_ptr, got_text, num_text);
+        }
+    }
+
+    /* Verify data */
+    png_get_text(png_ptr, info_ptr, &got_text, &num_text);
+    if (num_text != 12) {
+        fprintf(stderr, "FAIL: text count mismatch: %d\n", num_text);
+        goto fail;
+    }
+    if (strcmp(got_text[0].key, "Key1") != 0 || strcmp(got_text[11].text, "Value2") != 0) {
+        fprintf(stderr, "FAIL: text data corruption\n");
+        goto fail;
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+static int test_sPLT_aliasing(void) {
+    printf("Testing sPLT aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_sPLT_t splt;
+    png_sPLT_entry entries[1];
+    entries[0].red = 100; entries[0].green = 200; entries[0].blue = 300; entries[0].alpha = 400; entries[0].frequency = 500;
+    splt.name = (png_charp)"Test sPLT";
+    splt.depth = 8;
+    splt.entries = entries;
+    splt.nentries = 1;
+
+    png_set_sPLT(png_ptr, info_ptr, &splt, 1);
+
+    png_sPLT_tp got_splt;
+    int num_splt = (int)png_get_sPLT(png_ptr, info_ptr, &got_splt);
+
+    /* Critical call: got_splt aliases internal info_ptr->splt_palettes */
+    png_set_sPLT(png_ptr, info_ptr, got_splt, num_splt);
+
+    /* Verify data */
+    num_splt = (int)png_get_sPLT(png_ptr, info_ptr, &got_splt);
+    if (num_splt != 2) {
+        fprintf(stderr, "FAIL: sPLT count mismatch: %d\n", num_splt);
+        goto fail;
+    }
+    if (strcmp(got_splt[0].name, "Test sPLT") != 0 || got_splt[1].entries[0].red != 100) {
+        fprintf(stderr, "FAIL: sPLT data corruption\n");
+        goto fail;
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+#endif
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+static int test_unknown_aliasing(void) {
+    printf("Testing unknown chunks aliasing... ");
+    png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (!png_ptr) return 1;
+    png_infop info_ptr = png_create_info_struct(png_ptr);
+    if (!info_ptr) {
+        png_destroy_write_struct(&png_ptr, NULL);
+        return 1;
+    }
+
+    if (setjmp(png_jmpbuf(png_ptr))) {
+        png_destroy_write_struct(&png_ptr, &info_ptr);
+        return 1;
+    }
+
+    png_unknown_chunk unknowns[1];
+    memcpy(unknowns[0].name, "teSt", 5);
+    unknowns[0].data = (png_bytep)"TestData";
+    unknowns[0].size = 8;
+    unknowns[0].location = PNG_HAVE_IHDR;
+
+    png_set_unknown_chunks(png_ptr, info_ptr, unknowns, 1);
+
+    png_unknown_chunkp got_unknowns;
+    int num_unknowns = (int)png_get_unknown_chunks(png_ptr, info_ptr, &got_unknowns);
+
+    /* Critical call: got_unknowns aliases internal info_ptr->unknown_chunks */
+    png_set_unknown_chunks(png_ptr, info_ptr, got_unknowns, num_unknowns);
+
+    /* Verify data */
+    num_unknowns = (int)png_get_unknown_chunks(png_ptr, info_ptr, &got_unknowns);
+    if (num_unknowns != 2) {
+        fprintf(stderr, "FAIL: unknown chunks count mismatch: %d\n", num_unknowns);
+        goto fail;
+    }
+    if (memcmp(got_unknowns[0].name, "teSt", 4) != 0 || got_unknowns[1].size != 8) {
+        fprintf(stderr, "FAIL: unknown chunks data corruption\n");
+        goto fail;
+    }
+
+    printf("PASS\n");
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 0;
+
+fail:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    return 1;
+}
+#endif
+
+int main(void) {
+    int count = 0;
+    count += test_PLTE_aliasing();
+#ifdef PNG_hIST_SUPPORTED
+    count += test_hIST_aliasing();
+#endif
+#ifdef PNG_tRNS_SUPPORTED
+    count += test_tRNS_aliasing();
+#endif
+#ifdef PNG_TEXT_SUPPORTED
+    count += test_text_aliasing();
+#endif
+#ifdef PNG_sPLT_SUPPORTED
+    count += test_sPLT_aliasing();
+#endif
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+    count += test_unknown_aliasing();
+#endif
+
+    if (count == 0) {
+        printf("ALL ALIASING TESTS PASSED\n");
+        return 0;
+    }
+    printf("%d ALIASING TESTS FAILED\n", count);
+    return 1;
+}
