commit 4e38725fdcfc7c9216ecf38765a4321488b6f60c
parent a09ab061a5690800d1a388802d33692d380e6cb6
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 29 Jul 2026 11:04:48 +0200
preserve data on-stack to protect against override from subsequent read
Diffstat:
1 file changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/plugins/png_extractor.c b/src/plugins/png_extractor.c
@@ -489,40 +489,49 @@ EXTRACTOR_png_extract_method (struct EXTRACTOR_ExtractContext *ec)
ret = 0;
while (0 == ret)
{
- if (sizeof (uint32_t) + 4 !=
+ char chunk[sizeof (uint32_t) + 4];
+
+ if (sizeof (chunk) !=
ec->read (ec->cls,
&data,
- sizeof (uint32_t) + 4))
+ sizeof (chunk)))
break;
- length = get_int_at (data);
+ /* The pointer read() returns addresses the shared memory window and
+ is only valid until the next read() or seek() slides it. Both the
+ ec->seek() below and the process*() calls do that, so take a copy
+ of the chunk header before any of them runs. */
+ memcpy (chunk,
+ data,
+ sizeof (chunk));
+ length = get_int_at (chunk);
if (0 > (pos = ec->seek (ec->cls,
0,
SEEK_CUR)))
break;
pos += ((int64_t) length) + 4; /* Chunk type, data, crc */
- if (0 == strncmp ((char*) data + sizeof (uint32_t),
+ if (0 == strncmp (&chunk[sizeof (uint32_t)],
"IHDR",
4))
ret = processIHDR (ec,
length);
- if (0 == strncmp ((char*) data + sizeof (uint32_t),
- "iTXt",
- 4))
+ else if (0 == strncmp (&chunk[sizeof (uint32_t)],
+ "iTXt",
+ 4))
ret = processiTXt (ec,
length);
- if (0 == strncmp ((char*) data + sizeof (uint32_t),
- "tEXt",
- 4))
+ else if (0 == strncmp (&chunk[sizeof (uint32_t)],
+ "tEXt",
+ 4))
ret = processtEXt (ec,
length);
- if (0 == strncmp ((char*) data + sizeof (uint32_t),
- "zTXt",
- 4))
+ else if (0 == strncmp (&chunk[sizeof (uint32_t)],
+ "zTXt",
+ 4))
ret = processzTXt (ec,
length);
- if (0 == strncmp ((char*) data + sizeof (uint32_t),
- "tIME",
- 4))
+ else if (0 == strncmp (&chunk[sizeof (uint32_t)],
+ "tIME",
+ 4))
ret = processtIME (ec,
length);
if (ret != 0)