lib/decompress_unxz.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
When fill and flush are both NULL (single-call mode), unxz() takes
the xz_dec_run() fast path and skips straight to xz_dec_end(s),
bypassing the free(in)/free(b.out) cleanup that only runs inside the
multi-call (fill/flush) branch. If 'in' was NULL on entry, it gets
allocated locally (must_free_in = true) and is never freed on this
path, leaking XZ_IOBUF_SIZE bytes on every single-call decompression
that doesn't supply its own input buffer.
Move the must_free_in/flush cleanup out of the multi-call branch so
it runs after both paths.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=207113
Signed-off-by: Ivy Lopez <skunkolee@gmail.com>
---
lib/decompress_unxz.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c
index 05d5cb490a44..9ccded9934c6 100644
--- a/lib/decompress_unxz.c
+++ b/lib/decompress_unxz.c
@@ -342,13 +342,13 @@ STATIC int INIT unxz(unsigned char *in, long in_size,
b.out_pos = 0;
}
} while (ret == XZ_OK);
+ }
- if (must_free_in)
- free(in);
+ if (must_free_in)
+ free(in);
- if (flush != NULL)
- free(b.out);
- }
+ if (flush != NULL)
+ free(b.out);
if (in_used != NULL)
*in_used += b.in_pos;
--
2.55.0
On 2026-08-25 Ivy Lopez wrote: > When fill and flush are both NULL (single-call mode), unxz() takes > the xz_dec_run() fast path and skips straight to xz_dec_end(s), > bypassing the free(in)/free(b.out) cleanup that only runs inside the > multi-call (fill/flush) branch. If 'in' was NULL on entry, it gets > allocated locally (must_free_in = true) and is never freed on this > path, leaking XZ_IOBUF_SIZE bytes on every single-call decompression > that doesn't supply its own input buffer. There's no leak because calling with fill == NULL && flush == NULL && in == NULL is invalid. See this thread: https://lore.kernel.org/lkml/20241006072542.66442-2-t.v.s10123@gmail.com/T/ Maybe the code needs to be changed to prevent repeated attempts to "fix" it. I will get back to this in 1-3 days. -- Lasse Collin
The diff is good, but I would like a different commit message because there was no bug. I wrote a suggestion below. If you think it's OK, please submit v2 with the same diff and the new commit message to Andrew Morton. Thanks! ----%<---- lib: decompress_unxz: Make it obvious that there is no memory leak Calling __decompress() or unxz() with fill == NULL && flush == NULL && in == NULL is invalid, thus there were no memory leaks even though it might have looked like that. Move the conditional free() calls so that it's obvious that there are no leaks. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=207113 Link: https://lore.kernel.org/lkml/20241006072542.66442-2-t.v.s10123@gmail.com/T/ Link: https://lore.kernel.org/lkml/20260825191333.34276-1-skunkolee@gmail.com/T/ Reviewed-by: Lasse Collin <lasse.collin@tukaani.org> ----%<---- -- Lasse Collin
Calling __decompress() or unxz() with fill == NULL && flush == NULL &&
in == NULL is invalid, thus there were no memory leaks even though it
might have looked like that. Move the conditional free() calls so that
it's obvious that there are no leaks.
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=207113
Link: https://lore.kernel.org/lkml/20241006072542.66442-2-t.v.s10123@gmail.com/T/
Link: https://lore.kernel.org/lkml/20260825191333.34276-1-skunkolee@gmail.com/T/
Reviewed-by: Lasse Collin <lasse.collin@tukaani.org>
Signed-off-by: Ivy Lopez <skunkolee@gmail.com>
---
lib/decompress_unxz.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c
index 05d5cb490a44..9ccded9934c6 100644
--- a/lib/decompress_unxz.c
+++ b/lib/decompress_unxz.c
@@ -342,13 +342,13 @@ STATIC int INIT unxz(unsigned char *in, long in_size,
b.out_pos = 0;
}
} while (ret == XZ_OK);
+ }
- if (must_free_in)
- free(in);
+ if (must_free_in)
+ free(in);
- if (flush != NULL)
- free(b.out);
- }
+ if (flush != NULL)
+ free(b.out);
if (in_used != NULL)
*in_used += b.in_pos;
--
2.55.0
© 2016 - 2026 Red Hat, Inc.