From 0171fffd8b56b06be686f632138f23bc44d8c825 Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Sun, 26 May 2024 19:52:53 +0200
Subject: [PATCH] LZMADecode: zero-initialize (not-yet-written parts of) output
buffer if failure, and handle repeated calls to decoding same tile/strip if
previous failure occured
---
libtiff/tif_lzma.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libtiff/tif_lzma.c b/libtiff/tif_lzma.c
index 6fdc9280..1cc0f690 100644
--- a/libtiff/tif_lzma.c
+++ b/libtiff/tif_lzma.c
@@ -44,6 +44,8 @@
typedef struct
{
TIFFPredictorState predict;
+ int read_error; /* whether a read error has occurred, and which should cause
+ further reads in the same strip/tile to be aborted */
lzma_stream stream;
lzma_filter filters[LZMA_FILTERS_MAX + 1];
lzma_options_delta opt_delta; /* delta filter options */
@@ -156,6 +158,9 @@ static int LZMAPreDecode(TIFF *tif, uint16_t s)
LZMAStrerror(ret));
return 0;
}
+
+ sp->read_error = 0;
+
return 1;
}
@@ -168,6 +173,16 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
assert(sp != NULL);
assert(sp->state == LSTATE_INIT_DECODE);
+ if (sp->read_error)
+ {
+ memset(op, 0, (size_t)occ);
+ TIFFErrorExtR(tif, module,
+ "LZMADecode: Scanline %" PRIu32 " cannot be read due to "
+ "previous error",
+ tif->tif_row);
+ return 0;
+ }
+
sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (size_t)tif->tif_rawcc;
@@ -175,6 +190,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
sp->stream.avail_out = (size_t)occ;
if ((tmsize_t)sp->stream.avail_out != occ)
{
+ memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Liblzma cannot deal with buffers this size");
return 0;
@@ -198,6 +214,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0);
if (r != LZMA_OK)
{
+ sp->read_error = 1;
+ memset(op, 0, (size_t)occ);
TIFFErrorExtR(tif, module,
"Error initializing the stream decoder, %s",
LZMAStrerror(r));
@@ -217,6 +235,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
} while (sp->stream.avail_out > 0);
if (sp->stream.avail_out != 0)
{
+ sp->read_error = 1;
+ memset(sp->stream.next_out, 0, sp->stream.avail_out);
TIFFErrorExtR(tif, module,
"Not enough data at scanline %" PRIu32
" (short %" TIFF_SIZE_FORMAT " bytes)",