From 00c071dd11f723ca608608eef45cb1aa98da89cc Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Tue, 30 Apr 2024 07:26:54 -0500 Subject: [PATCH 1/3] ANI: Reject files with multiple anih chunks An anih chunk causes us to initialize a bunch of state, which we only expect to do once per file. Fixes: #202 Fixes: CVE-2022-48622 --- gdk-pixbuf/io-ani.c | 9 +++++++++ tests/test-images/fail/CVE-2022-48622.ani | Bin 0 -> 28012 bytes 2 files changed, 9 insertions(+) create mode 100644 tests/test-images/fail/CVE-2022-48622.ani diff --git a/gdk-pixbuf/io-ani.c b/gdk-pixbuf/io-ani.c index c6c4642cf4..a78ea7ace4 100644 --- a/gdk-pixbuf/io-ani.c +++ b/gdk-pixbuf/io-ani.c @@ -295,6 +295,15 @@ ani_load_chunk (AniLoaderContext *context, GError **error) if (context->chunk_id == TAG_anih) { + if (context->animation) + { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Invalid header in animation")); + return FALSE; + } + context->HeaderSize = read_int32 (context); context->NumFrames = read_int32 (context); context->NumSteps = read_int32 (context); diff --git a/tests/test-images/fail/CVE-2022-48622.ani b/tests/test-images/fail/CVE-2022-48622.ani new file mode 100644 index 0000000000000000000000000000000000000000..276b5b989f1e9ec9185e49eb45f710ee38278eb2 GIT binary patch literal 28012 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 Date: Tue, 30 Apr 2024 07:13:37 -0500 Subject: [PATCH 2/3] ANI: Reject files with multiple INAM or IART chunks There should be at most one chunk each. These would cause memory leaks otherwise. --- gdk-pixbuf/io-ani.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gdk-pixbuf/io-ani.c b/gdk-pixbuf/io-ani.c index a78ea7ace4..8e8414117c 100644 --- a/gdk-pixbuf/io-ani.c +++ b/gdk-pixbuf/io-ani.c @@ -445,7 +445,7 @@ ani_load_chunk (AniLoaderContext *context, GError **error) } else if (context->chunk_id == TAG_INAM) { - if (!context->animation) + if (!context->animation || context->title) { g_set_error_literal (error, GDK_PIXBUF_ERROR, @@ -472,7 +472,7 @@ ani_load_chunk (AniLoaderContext *context, GError **error) } else if (context->chunk_id == TAG_IART) { - if (!context->animation) + if (!context->animation || context->author) { g_set_error_literal (error, GDK_PIXBUF_ERROR, -- GitLab From 91b8aa5cd8a0eea28acb51f0e121827ca2e7eb78 Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Tue, 30 Apr 2024 08:17:25 -0500 Subject: [PATCH 3/3] ANI: Validate anih chunk size Before reading a chunk, we verify that enough bytes are available to match the chunk size declared by the file. However, uniquely, the anih chunk loader doesn't verify that this size matches the number of bytes it actually intends to read. Thus, if the chunk size is too small and the file ends in the middle of the chunk, we populate some context fields with stack garbage. (But we'd still fail later on because the file doesn't contain any images.) Fix this. --- gdk-pixbuf/io-ani.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gdk-pixbuf/io-ani.c b/gdk-pixbuf/io-ani.c index 8e8414117c..cfafd7b196 100644 --- a/gdk-pixbuf/io-ani.c +++ b/gdk-pixbuf/io-ani.c @@ -295,6 +295,14 @@ ani_load_chunk (AniLoaderContext *context, GError **error) if (context->chunk_id == TAG_anih) { + if (context->chunk_size < 36) + { + g_set_error_literal (error, + GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Malformed chunk in animation")); + return FALSE; + } if (context->animation) { g_set_error_literal (error, -- GitLab