PR #25339 opened by Daniel Brodie (danielbrodie) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25339 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25339.patch
# Summary of changes Fixes #25284. `ff_lzf_uncompress()` looped while more than 2 bytes were left, so a stream ending in a one-byte literal run or a short back-reference lost its last token and the output came out short. liblzf can end a stream that way. The `> 2` dates from the original decompressor (0c7707610f). Literal runs are already checked against the input since 610d368d9b; this adds the same check for back-references, so a truncated stream still returns AVERROR_INVALIDDATA. Tested on master adfe258a6a: - the sample attached to #25284 now decodes every frame (before: none), and the full 300-frame export it was cut from decodes 300/300 frames, framemd5-identical to the LZ4 original; - all fate-dxv tests pass, including the two that use LZF (dxv-na, dxv-wa); - make fate (Windows, MSYS2 MINGW64, full fate-suite): the 15 failures also fail on unpatched master; - 200 decodes of damaged copies (random byte changes inside mdat) gave no crashes or hangs. AI disclosure: AI was used for investigation and development of this patch. >From 8699164b77098d2f541333929c6f0cf7a0d8a141 Mon Sep 17 00:00:00 2001 From: Daniel Brodie <[email protected]> Date: Wed, 21 Oct 2026 14:43:02 -0400 Subject: [PATCH] avcodec/lzf: decode a final token shorter than 3 bytes The loop stopped with 2 bytes left, so a stream ending in a one-byte literal run or a short back-reference lost its last token and the output came out short. liblzf can end a stream that way. Check that each back-reference has its bytes instead. Fixes: #25284 Signed-off-by: Daniel Brodie <[email protected]> --- libavcodec/lzf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/lzf.c b/libavcodec/lzf.c index 1c38c98982e..7cce124efd9 100644 --- a/libavcodec/lzf.c +++ b/libavcodec/lzf.c @@ -58,7 +58,7 @@ int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, size_t *size, unsigned uint8_t *p = *buf; int64_t len = 0; - while (bytestream2_get_bytes_left(gb) > 2) { + while (bytestream2_get_bytes_left(gb) > 0) { uint8_t s = bytestream2_get_byte(gb); if (s < LZF_LITERAL_MAX) { @@ -80,6 +80,9 @@ int ff_lzf_uncompress(GetByteContext *gb, uint8_t **buf, size_t *size, unsigned int l = 2 + (s >> 5); int off = ((s & 0x1f) << 8) + 1; + if (bytestream2_get_bytes_left(gb) < 1 + (l == LZF_LONG_BACKREF)) + return AVERROR_INVALIDDATA; + if (l == LZF_LONG_BACKREF) l += bytestream2_get_byte(gb); -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
