From patchwork Sun Nov 23 23:44:57 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Murray X-Patchwork-Id: 75286 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 84763CFD31F for ; Sun, 23 Nov 2025 23:45:43 +0000 (UTC) Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.5044.1763941535564258155 for ; Sun, 23 Nov 2025 15:45:35 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@konsulko.com header.s=google header.b=kwOtWN6n; spf=pass (domain: konsulko.com, ip: 209.85.222.171, mailfrom: scott.murray@konsulko.com) Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-8b22b1d3e7fso386925185a.3 for ; Sun, 23 Nov 2025 15:45:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=konsulko.com; s=google; t=1763941534; x=1764546334; darn=lists.yoctoproject.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=mkDQAqyryP/0ijH7+ENgqxvOCZJY4Csst8amGLL59FM=; b=kwOtWN6ndP4IJZcN4PGnC+D6J7RdJhstW3QSBsD3OTHZGam40wMn2pEEc+MgTB4R/n pxeRyWCzDOEZMOss3/6/Q/8NIvkMzIpYy7rQ5ZAbqoq3exeOwy2TrB30dD7JSSdfNwiS 47xW07QiXkAFnDMiMPPkUsoHHodgvEMdaGjVI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763941534; x=1764546334; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=mkDQAqyryP/0ijH7+ENgqxvOCZJY4Csst8amGLL59FM=; b=A2M4kHXzAgZZjYyRDGTuC6SIUCQJcpZfY5IvYkH0DTR9cnGlJilludAkwLSdAd4XV/ 8+1Vbt6vXzmmiKikGJ0uTQVxbIiaX5m8PESW+D2Z9dMWKbC9PYFLdI4csvG0EGCYvM3C KcVE47rgNwVgfXbGPy/1A3gx63GlGFkVJ9Gz2okmPhmiONs15ke76IC0Px0v6v8q8buF hNvM152as/2hOOjN5k3s20Frx4kGoluWytbRvdR9MNMFZvewqqFhQPooQGTz8qMbAE7h tbygfRHBgfmQ6wH5qbk+JuE5/Uzl/as1HcH2KHUDlqgK1L0xH4DV2sAZro9sSQfui94p T2wQ== X-Gm-Message-State: AOJu0YwvgHCB8JLTkAT5qVJ/kZoyXzqodaoakS6Edx3ORPUsvPbY97YK Rlra10miWdoFgNxiOju9dSBcHLGgWyT8bHASshZvOoOlW0fPBmgFdLjdOsad2hZQEcOT2hgHlH8 V3QFM X-Gm-Gg: ASbGnctuWPLS/2lj75twtQMhhyvQgS+tNf0gYxr0i6Aj7kVKJgA+ihhl7SiG+8QK9gt tBDvgumcrTjapki1vqQ7e2xYgx5h9lP2nHOYDOLwi0RrvFudFvLeWIECe9U7tA0RkOpw761opJd IFTZ8xuqHojZDVkbo/+nLotUKW0t0dc6ZtTguVio1wLQhPhGDKpAAxvOH/yATJS/tq9Q/YnAYo/ Aez2WLOq48tRI7tZ4KMQx/2esDr4XdlE6VrWmvNb+zXN8vwFmgpNsaaW2cpfNp6KfG2eXl1fb76 D8Ur7G5NxWJNXjBk9F5nzqOJ3caqc8uAkHNAxpmUgTwmtmn4elyPpxSvdAdO4XrZ+lxPalkm3OL mS51sQRW8u0kkr55OHJgXaRLbMDiZe8bmPq7/U2AQxU4ts2fHzrENYnleRvxDWOYbpNNVhMSBkH bFby2jIFpuvCkwnX9+zk/ud2P+AIMalkcGECOMwUmxNI/CASnvn5UUHDbh87RgIoA= X-Google-Smtp-Source: AGHT+IGm21/Q6KbOFeGj9fKAXwOPIpDJJvd+rvv1/U9Ln+sz+aoKgOm5mBtbOBI4pgQ110nMKzhZ0w== X-Received: by 2002:a05:620a:25c8:b0:8b2:e827:14bc with SMTP id af79cd13be357-8b33d4cfac2mr1209583885a.56.1763941533965; Sun, 23 Nov 2025 15:45:33 -0800 (PST) Received: from ghidorah.spiteful.org (107-179-213-3.cpe.teksavvy.com. [107.179.213.3]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8b32932db59sm843706585a.1.2025.11.23.15.45.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Nov 2025 15:45:33 -0800 (PST) From: Scott Murray To: yocto-patches@lists.yoctoproject.org Subject: [meta-security][scarthgap][PATCH 17/32] clamav: fix CVE-2025-20260 Date: Sun, 23 Nov 2025 18:44:57 -0500 Message-ID: <1fcb48fd8e2d4c1ab60d36988ff58671cccacf22.1763938436.git.scott.murray@konsulko.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 23 Nov 2025 23:45:43 -0000 X-Groupsio-URL: https://lists.yoctoproject.org/g/yocto-patches/message/2675 From: Hitendra Prajapati Upstream-Status: Backport https://github.com/Cisco-Talos/clamav/commit/7fe290b573db66ffcf590902977b2b6043b30834 Signed-off-by: Hitendra Prajapati Signed-off-by: Scott Murray --- recipes-scanners/clamav/clamav_0.104.4.bb | 1 + .../clamav/files/CVE-2025-20260.patch | 366 ++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 recipes-scanners/clamav/files/CVE-2025-20260.patch diff --git a/recipes-scanners/clamav/clamav_0.104.4.bb b/recipes-scanners/clamav/clamav_0.104.4.bb index d7beade..0bd776c 100644 --- a/recipes-scanners/clamav/clamav_0.104.4.bb +++ b/recipes-scanners/clamav/clamav_0.104.4.bb @@ -22,6 +22,7 @@ SRC_URI = "git://github.com/Cisco-Talos/clamav;branch=rel/0.104;protocol=https \ file://oe_cmake_fixup.patch \ file://CVE-2024-20505.patch \ file://CVE-2024-20506.patch \ + file://CVE-2025-20260.patch \ " S = "${WORKDIR}/git" diff --git a/recipes-scanners/clamav/files/CVE-2025-20260.patch b/recipes-scanners/clamav/files/CVE-2025-20260.patch new file mode 100644 index 0000000..6177d4b --- /dev/null +++ b/recipes-scanners/clamav/files/CVE-2025-20260.patch @@ -0,0 +1,366 @@ +From 7fe290b573db66ffcf590902977b2b6043b30834 Mon Sep 17 00:00:00 2001 +From: John Humlick <15677335+jhumlick@users.noreply.github.com> +Date: Mon, 21 Apr 2025 16:18:07 -0700 +Subject: [PATCH] Fix integer overflow in PDF parser + +The ascii85decode function calculates the amount of memory to reserve as +a function of (4 * bytes) + 1. Since the result is stored in a uint32_t, +we need to make sure that this calculation will not overflow. If we +detect that an overflow would occur, return CL_EFORMAT and do not +proceed. + +Also check additional potential overflow conditions. +Other areas were identified that could potentially overflow. +This commit adds additional checks to prevent said overflows. + +Thank you Greg Walkup at Sandia National Labs for reporting this issue. + +CLAM-2752 +CLAM-2757 +CLAM-2759 + +Upstream-Status: Backport [https://github.com/Cisco-Talos/clamav/commit/7fe290b573db66ffcf590902977b2b6043b30834] +CVE: CVE-2025-20260 +Signed-off-by: Hitendra Prajapati +--- + libclamav/pdf.c | 42 +++++++++++------------ + libclamav/pdf.h | 16 ++++----- + libclamav/pdfdecode.c | 80 +++++++++++++++++++++++++++++++------------ + 3 files changed, 87 insertions(+), 51 deletions(-) + +diff --git a/libclamav/pdf.c b/libclamav/pdf.c +index 40eea19eb..a305b1701 100644 +--- a/libclamav/pdf.c ++++ b/libclamav/pdf.c +@@ -441,7 +441,7 @@ int pdf_findobj_in_objstm(struct pdf_struct *pdf, struct objstm_struct *objstm, + + if (CL_SUCCESS != cli_strntol_wrap(index, bytes_remaining, 0, 10, &temp_long)) { + /* Failed to find obj offset for next obj */ +- cli_dbgmsg("pdf_findobj_in_objstm: Failed to find next obj offset for obj in object stream though there should be {%u} more.\n", objstm->n - objstm->nobjs_found); ++ cli_dbgmsg("pdf_findobj_in_objstm: Failed to find next obj offset for obj in object stream though there should be {%zu} more.\n", objstm->n - objstm->nobjs_found); + status = CL_EPARSE; + goto done; + } else if (temp_long < 0) { +@@ -1551,18 +1551,18 @@ cl_error_t pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t + } + } + +- cli_dbgmsg("pdf_extract_obj: calculated length %lld\n", (long long)length); ++ cli_dbgmsg("pdf_extract_obj: calculated length %zu\n", length); + } else { + if (obj->stream_size > (size_t)length + 2) { + cli_dbgmsg("cli_pdf: calculated length %zu < %zu\n", +- (size_t)length, obj->stream_size); ++ length, obj->stream_size); + length = obj->stream_size; + } + } + +- if ((0 != orig_length) && (obj->stream_size > (size_t)orig_length + 20)) { +- cli_dbgmsg("pdf_extract_obj: orig length: %lld, length: %lld, size: %zu\n", +- (long long)orig_length, (long long)length, obj->stream_size); ++ if ((0 != orig_length) && (obj->stream_size > orig_length + 20)) { ++ cli_dbgmsg("pdf_extract_obj: orig length: %zu, length: %zu, size: %zu\n", ++ orig_length, length, obj->stream_size); + pdfobj_flag(pdf, obj, BAD_STREAMLEN); + } + +@@ -1613,18 +1613,18 @@ cl_error_t pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t + */ + dict_len = obj->stream - start; + if (NULL != (pstr = pdf_getdict(start, &dict_len, "/Type/ObjStm"))) { +- int32_t objstm_first = -1; +- int32_t objstm_length = -1; +- int32_t objstm_n = -1; ++ int objstm_first = -1; ++ int objstm_length = -1; ++ int objstm_n = -1; + + cli_dbgmsg("pdf_extract_obj: Found /Type/ObjStm\n"); + + dict_len = obj->stream - start; +- if ((-1 == (objstm_first = pdf_readint(start, dict_len, "/First")))) { ++ if (-1 == (objstm_first = pdf_readint(start, dict_len, "/First"))) { + cli_warnmsg("pdf_extract_obj: Failed to find offset of first object in object stream\n"); +- } else if ((-1 == (objstm_length = pdf_readint(start, dict_len, "/Length")))) { ++ } else if (-1 == (objstm_length = pdf_readint(start, dict_len, "/Length"))) { + cli_warnmsg("pdf_extract_obj: Failed to find length of object stream\n"); +- } else if ((-1 == (objstm_n = pdf_readint(start, dict_len, "/N")))) { ++ } else if (-1 == (objstm_n = pdf_readint(start, dict_len, "/N"))) { + cli_warnmsg("pdf_extract_obj: Failed to find num objects in object stream\n"); + } else { + /* Add objstm to pdf struct, so it can be freed eventually */ +@@ -1646,19 +1646,19 @@ cl_error_t pdf_extract_obj(struct pdf_struct *pdf, struct pdf_obj *obj, uint32_t + + memset(objstm, 0, sizeof(*objstm)); + +- objstm->first = (uint32_t)objstm_first; +- objstm->current = (uint32_t)objstm_first; ++ objstm->first = (size_t)objstm_first; ++ objstm->current = (size_t)objstm_first; + objstm->current_pair = 0; +- objstm->length = (uint32_t)objstm_length; +- objstm->n = (uint32_t)objstm_n; ++ objstm->length = (size_t)objstm_length; ++ objstm->n = (size_t)objstm_n; + +- cli_dbgmsg("pdf_extract_obj: ObjStm first obj at offset %d\n", objstm->first); +- cli_dbgmsg("pdf_extract_obj: ObjStm length is %d bytes\n", objstm->length); +- cli_dbgmsg("pdf_extract_obj: ObjStm should contain %d objects\n", objstm->n); ++ cli_dbgmsg("pdf_extract_obj: ObjStm first obj at offset %zu\n", objstm->first); ++ cli_dbgmsg("pdf_extract_obj: ObjStm length is %zu bytes\n", objstm->length); ++ cli_dbgmsg("pdf_extract_obj: ObjStm should contain %zu objects\n", objstm->n); + } + } + +- sum = pdf_decodestream(pdf, obj, dparams, obj->stream, (uint32_t)length, xref, fout, &rc, objstm); ++ sum = pdf_decodestream(pdf, obj, dparams, obj->stream, length, xref, fout, &rc, objstm); + if ((CL_SUCCESS != rc) && (CL_VIRUS != rc)) { + cli_dbgmsg("Error decoding stream! Error code: %d\n", rc); + +@@ -3341,7 +3341,7 @@ cl_error_t pdf_find_and_parse_objs_in_objstm(struct pdf_struct *pdf, struct objs + retval = pdf_findobj_in_objstm(pdf, objstm, &obj); + if (retval != CL_SUCCESS) { + if (retval != CL_BREAK) { +- cli_dbgmsg("pdf_find_and_parse_objs_in_objstm: Fewer objects in stream than expected: %u found, %u expected.\n", ++ cli_dbgmsg("pdf_find_and_parse_objs_in_objstm: Fewer objects in stream than expected: %zu found, %zu expected.\n", + objstm->nobjs_found, objstm->n); + badobjects++; + pdf->stats.ninvalidobjs++; +diff --git a/libclamav/pdf.h b/libclamav/pdf.h +index 3a03f19f1..b5b69cec7 100644 +--- a/libclamav/pdf.h ++++ b/libclamav/pdf.h +@@ -25,14 +25,14 @@ + #define PDF_FILTERLIST_MAX 64 + + struct objstm_struct { +- uint32_t first; // offset of first obj +- uint32_t current; // offset of current obj +- uint32_t current_pair; // offset of current pair describing id, location of object +- uint32_t length; // total length of all objects (starting at first) +- uint32_t n; // number of objects that should be found in the object stream +- uint32_t nobjs_found; // number of objects actually found in the object stream +- char *streambuf; // address of stream buffer, beginning with first obj pair +- size_t streambuf_len; // length of stream buffer, includes pairs followed by actual objects ++ size_t first; // offset of first obj ++ size_t current; // offset of current obj ++ size_t current_pair; // offset of current pair describing id, location of object ++ size_t length; // total length of all objects (starting at first) ++ size_t n; // number of objects that should be found in the object stream ++ size_t nobjs_found; // number of objects actually found in the object stream ++ char *streambuf; // address of stream buffer, beginning with first obj pair ++ size_t streambuf_len; // length of stream buffer, includes pairs followed by actual objects + }; + + struct pdf_obj { +diff --git a/libclamav/pdfdecode.c b/libclamav/pdfdecode.c +index 473cfcd43..92ba52d50 100644 +--- a/libclamav/pdfdecode.c ++++ b/libclamav/pdfdecode.c +@@ -73,7 +73,7 @@ + struct pdf_token { + uint32_t flags; /* tracking flags */ + uint32_t success; /* successfully decoded filters */ +- uint32_t length; /* length of current content; TODO: transition to size_t */ ++ size_t length; /* length of current content; TODO: transition to size_t */ + uint8_t *content; /* content stream */ + }; + +@@ -461,10 +461,16 @@ static cl_error_t filter_ascii85decode(struct pdf_struct *pdf, struct pdf_obj *o + uint32_t declen = 0; + + const uint8_t *ptr = (uint8_t *)token->content; +- uint32_t remaining = token->length; ++ size_t remaining = token->length; + int quintet = 0, rc = CL_SUCCESS; + uint64_t sum = 0; + ++ /* Check for overflow */ ++ if (remaining > (SIZE_MAX / 4)) { ++ cli_dbgmsg("cli_pdf: ascii85decode: overflow detected\n"); ++ return CL_EFORMAT; ++ } ++ + /* 5:4 decoding ratio, with 1:4 expansion sequences => (4*length)+1 */ + if (!(dptr = decoded = (uint8_t *)cli_malloc((4 * remaining) + 1))) { + cli_errmsg("cli_pdf: cannot allocate memory for decoded output\n"); +@@ -851,8 +857,8 @@ static cl_error_t filter_asciihexdecode(struct pdf_struct *pdf, struct pdf_obj * + uint8_t *decoded; + + const uint8_t *content = (uint8_t *)token->content; +- uint32_t length = token->length; +- uint32_t i, j; ++ size_t length = token->length; ++ size_t i, j; + cl_error_t rc = CL_SUCCESS; + + if (!(decoded = (uint8_t *)cli_calloc(length / 2 + 1, sizeof(uint8_t)))) { +@@ -882,8 +888,8 @@ static cl_error_t filter_asciihexdecode(struct pdf_struct *pdf, struct pdf_obj * + if (rc == CL_SUCCESS) { + free(token->content); + +- cli_dbgmsg("cli_pdf: deflated %lu bytes from %lu total bytes\n", +- (unsigned long)j, (unsigned long)(token->length)); ++ cli_dbgmsg("cli_pdf: deflated %zu bytes from %zu total bytes\n", ++ j, token->length); + + token->content = decoded; + token->length = j; +@@ -891,8 +897,8 @@ static cl_error_t filter_asciihexdecode(struct pdf_struct *pdf, struct pdf_obj * + if (!(obj->flags & ((1 << OBJ_IMAGE) | (1 << OBJ_TRUNCATED)))) + pdfobj_flag(pdf, obj, BAD_ASCIIDECODE); + +- cli_dbgmsg("cli_pdf: error occurred parsing byte %lu of %lu\n", +- (unsigned long)i, (unsigned long)(token->length)); ++ cli_dbgmsg("cli_pdf: error occurred parsing byte %zu of %zu\n", ++ i, token->length); + free(decoded); + } + return rc; +@@ -933,27 +939,29 @@ static cl_error_t filter_decrypt(struct pdf_struct *pdf, struct pdf_obj *obj, st + return CL_EPARSE; /* TODO: what should this value be? CL_SUCCESS would mirror previous behavior */ + } + +- cli_dbgmsg("cli_pdf: decrypted %zu bytes from %u total bytes\n", ++ cli_dbgmsg("cli_pdf: decrypted %zu bytes from %zu total bytes\n", + length, token->length); + + free(token->content); + token->content = (uint8_t *)decrypted; +- token->length = (uint32_t)length; /* this may truncate unfortunately, TODO: use 64-bit values internally? */ ++ token->length = length; + return CL_SUCCESS; + } + + static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, struct pdf_dict *params, struct pdf_token *token) + { + uint8_t *decoded, *temp; +- uint32_t declen = 0, capacity = 0; ++ size_t declen = 0, capacity = 0; + + uint8_t *content = (uint8_t *)token->content; + uint32_t length = token->length; + lzw_stream stream; + int echg = 1, lzwstat, rc = CL_SUCCESS; + +- if (pdf->ctx && !(pdf->ctx->dconf->other & OTHER_CONF_LZW)) +- return CL_BREAK; ++ if (pdf->ctx && !(pdf->ctx->dconf->other & OTHER_CONF_LZW)) { ++ rc = CL_BREAK; ++ goto done; ++ } + + if (params) { + struct pdf_dict_node *node = params->nodes; +@@ -984,15 +992,18 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + * Sample 0015315109, it has \r followed by zlib header. + * Flag pdf as suspicious, and attempt to extract by skipping the \r. + */ +- if (!length) +- return CL_SUCCESS; ++ if (!length) { ++ rc = CL_SUCCESS; ++ goto done; ++ } + } + + capacity = INFLATE_CHUNK_SIZE; + + if (!(decoded = (uint8_t *)cli_malloc(capacity))) { + cli_errmsg("cli_pdf: cannot allocate memory for decoded output\n"); +- return CL_EMEM; ++ rc = CL_EMEM; ++ goto done; + } + + memset(&stream, 0, sizeof(stream)); +@@ -1007,7 +1018,8 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + if (lzwstat != Z_OK) { + cli_warnmsg("cli_pdf: lzwInit failed\n"); + free(decoded); +- return CL_EMEM; ++ rc = CL_EMEM; ++ goto done; + } + + /* initial inflate */ +@@ -1022,16 +1034,23 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + length -= q - content; + content = q; + +- stream.next_in = (Bytef *)content; +- stream.avail_in = length; +- stream.next_out = (Bytef *)decoded; ++ stream.next_in = (Bytef *)content; ++ stream.avail_in = length; ++ stream.next_out = (Bytef *)decoded; ++ /* Make sure we don't overflow during type conversion */ ++ if (capacity > UINT_MAX) { ++ cli_dbgmsg("cli_pdf: lzwdecode: overflow detected\n"); ++ rc = CL_EFORMAT; ++ goto done; ++ } + stream.avail_out = capacity; + + lzwstat = lzwInit(&stream); + if (lzwstat != Z_OK) { + cli_warnmsg("cli_pdf: lzwInit failed\n"); + free(decoded); +- return CL_EMEM; ++ rc = CL_EMEM; ++ goto done; + } + + pdfobj_flag(pdf, obj, BAD_FLATESTART); +@@ -1044,7 +1063,7 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + /* extend output capacity if needed,*/ + if (stream.avail_out == 0) { + if ((rc = cli_checklimits("pdf", pdf->ctx, capacity + INFLATE_CHUNK_SIZE, 0, 0)) != CL_SUCCESS) { +- cli_dbgmsg("cli_pdf: required buffer size to inflate compressed filter exceeds maximum: %u\n", capacity + INFLATE_CHUNK_SIZE); ++ cli_dbgmsg("cli_pdf: required buffer size to inflate compressed filter exceeds maximum: %zu\n", capacity + INFLATE_CHUNK_SIZE); + break; + } + +@@ -1056,7 +1075,17 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + decoded = temp; + stream.next_out = decoded + capacity; + stream.avail_out = INFLATE_CHUNK_SIZE; ++ if (declen > (SIZE_MAX - INFLATE_CHUNK_SIZE)) { ++ cli_dbgmsg("cli_pdf: lzwdecode: overflow detected\n"); ++ rc = CL_EFORMAT; ++ goto done; ++ } + declen += INFLATE_CHUNK_SIZE; ++ if (capacity > (SIZE_MAX - INFLATE_CHUNK_SIZE)) { ++ cli_dbgmsg("cli_pdf: lzwdecode: overflow detected\n"); ++ rc = CL_EFORMAT; ++ goto done; ++ } + capacity += INFLATE_CHUNK_SIZE; + } + +@@ -1064,6 +1093,12 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + lzwstat = lzwInflate(&stream); + } + ++ if (declen > (UINT32_MAX - (INFLATE_CHUNK_SIZE - stream.avail_out))) { ++ cli_dbgmsg("cli_pdf: lzwdecode: overflow detected\n"); ++ rc = CL_EFORMAT; ++ goto done; ++ } ++ + /* add stream end fragment to decoded length */ + declen += (INFLATE_CHUNK_SIZE - stream.avail_out); + +@@ -1104,6 +1139,7 @@ static cl_error_t filter_lzwdecode(struct pdf_struct *pdf, struct pdf_obj *obj, + + (void)lzwInflateEnd(&stream); + ++done: + if (rc == CL_SUCCESS) { + if (declen == 0) { + cli_dbgmsg("cli_pdf: empty stream after inflation completed.\n"); +-- +2.49.0 +