This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 705286a8a7 avcodec/fflcms2: fix memory leak after
cmsDeleteContext(NULL)
705286a8a7 is described below
commit 705286a8a7a8f9118465b2bd83f99a6f066dcbbc
Author: David Tolnay <[email protected]>
AuthorDate: Mon Sep 7 17:09:55 2026 -0700
Commit: Niklas Haas <[email protected]>
CommitDate: Tue Sep 8 23:59:36 2026 +0000
avcodec/fflcms2: fix memory leak after cmsDeleteContext(NULL)
At the time that this code was introduced into FFmpeg in April 2022 by
commit
b9a25963f7232433c9370ac369fb668ac0d5cb53, it was correct as written. The
latest release of
lcms2 at the time was 2.13.1 in which `cmsDeleteContext(NULL)` was a no-op.
Since lcms2 version 2.15, released Mar 2023, the same call is no longer a
no-op and
instead means destroy the global context. The new behavior is justifiable
as being
consistent with the rest of lcms2's API, where passing NULL for a
cmsContext argument
means operate on the global context. For example `cmsDupContext(NULL, ...)`
constructs a
context duplicated from the global context; `cmsPluginTHR(NULL, ...)`
registers a plugin
into the global context.
The upstream commit that introduced the behavior change for
`cmsDeleteContext` is:
https://github.com/mm2/Little-CMS/commit/a9e4601ceb3a185d4f78cc0cfbd285cf0c399e9d
In FFmpeg, the new behavior leads to a memory leak if
`ff_icc_context_uninit` is ever
called on an `FFIccContext` without `ff_icc_context_init`. Here is why that
can happen,
and here is how it leads to a memory leak.
Naively, uninitializing something which was never initialized seems like it
shouldn't
happen, but in this case these contexts are *lazily* initialized and
*unconditionally*
deinitialized. `FFIccContext` is a member of `AVCodecInternal`:
// libavcodec/internal.h:148-150
#if CONFIG_LCMS2
FFIccContext icc; /* used to read and write embedded ICC profiles */
#endif
It is initialized conditionally by the snippet of `detect_colorspace` shown
below, or by
similary shaped code in libavcodec/encode.c. The `avci->icc.avctx` guards
"has it already
been initialized". The early returns beforehand are codepaths for which
`icc` will not be
initialized, and will remain all-zero as allocated by `av_mallocz` in
`ff_decode_internal_alloc`.
// libavcodec/decode.c:534-542
if (!(avctx->flags2 & AV_CODEC_FLAG2_ICC_PROFILES))
return 0;
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
if (!sd || !sd->size)
return 0;
if (!avci->icc.avctx) {
ret = ff_icc_context_init(&avci->icc, avctx);
Later, `avci->icc` is uninitialized unconditionally by `ff_codec_close`:
// libavcodec/avcodec.c:447-480
if (avcodec_is_open(avctx)) {
...
#if CONFIG_LCMS2
ff_icc_context_uninit(&avci->icc);
#endif
So every codec closed without `AV_CODEC_FLAGS2_ICC_PROFILES`, or without an
ICC side-data
packet, reaches `ff_icc_context_uninit` on a never-initialized context.
As part of `cmsDeleteContext(NULL)` destroying lcms2's global context, it
runs
`cmsUnregisterPlugins()` and destroys `globalContext.MemPool`. Since the
global context is
shared by every user of lcms2 in the process, closing an FFmpeg codec
silently tears down
unrelated libraries' lcms2 state. The most visible symptom is that
`_cmsRegisterMutexPlugin(NULL, NULL)` nulls out the mutex callbacks, after
which
`cmsCloseProfile()` leaks each profile's `UsrMutex` and profiles opened
later are left
without any locking at all.
The fix is to delete only contexts created by FFmpeg.
Signed-off-by: David Tolnay <[email protected]>
---
libavcodec/fflcms2.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c
index 3c7f3dc07f..5e2215bce5 100644
--- a/libavcodec/fflcms2.c
+++ b/libavcodec/fflcms2.c
@@ -43,7 +43,8 @@ void ff_icc_context_uninit(FFIccContext *s)
{
for (int i = 0; i < FF_ARRAY_ELEMS(s->curves); i++)
cmsFreeToneCurve(s->curves[i]);
- cmsDeleteContext(s->ctx);
+ if (s->ctx)
+ cmsDeleteContext(s->ctx);
memset(s, 0, sizeof(*s));
}
--
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]