Skip to content
Merged
17 changes: 17 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
poppler (22.12.0-2+deb12u3deepin1) unstable; urgency=medium

* fix(cve): CVE-2026-93314 (medium) - FoFiTrueType::mapCodeToGID: Improve
b*12 overflow check
* fix(cve): CVE-2026-93313 (medium) - Fix integer overflow in
JBIG2Stream::readCodeTableSeg
* fix(cve): CVE-2026-93312 (medium) - Fix nullptr dereference in
JBIG2Stream::reset
* fix(cve): CVE-2026-107705 (high) - Decrypt: Properly apply password
length limit
* fix(cve): CVE-2026-102621 - Fix integer overflow in
SplashClip::clipToPath
* fix(cve): CVE-2026-102620 - Fix integer overflow in
FoFiTrueType::cvtSfnts

-- deepin-ci-robot <packages@deepin.org> Thu, 08 Oct 2026 16:52:09 +0800

poppler (22.12.0-2+deb12u3) bookworm-security; urgency=high

* Non-maintainer upload by the LTS Team.
Expand Down
31 changes: 31 additions & 0 deletions debian/patches/CVE-2026-102620.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Description: CVE-2026-102620 (unknown) - CVE-2026-102620 兼容性修复:添加 GooCheckedOps.h 头文件包含
Author: deepin-ci-robot <packages@deepin.org>
Origin: N/A
Bug: https://nvd.nist.gov/vuln/detail/CVE-2026-102620
Last-Update: 2026-10-10
---
diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
index 71d8415..113529a 100644
--- a/fofi/FoFiTrueType.cc
+++ b/fofi/FoFiTrueType.cc
@@ -40,6 +40,7 @@
#include <algorithm>
#include "goo/gmem.h"
#include "goo/GooLikely.h"
+#include "goo/GooCheckedOps.h"
#include "goo/GooString.h"
#include "FoFiType1C.h"
#include "FoFiTrueType.h"
@@ -1258,7 +1259,11 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const
checksum = 0;
glyfPos = tables[seekTable("glyf")].offset;
for (j = 0; j < nGlyphs; ++j) {
- length += locaTable[j].len;
+ if (unlikely(checkedAdd(length, locaTable[j].len, &length))) {
+ error(errSyntaxError, -1, "Integer overflow in glyph table length calculation");
+ ok = false;
+ break;
+ }
if (length & 3) {
length += 4 - (length & 3);
}
34 changes: 34 additions & 0 deletions debian/patches/CVE-2026-102621.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Description: CVE-2026-102621 (unknown) - A vulnerability was identified in Freedesktop Poppler up to 26.08.0. Affected is the function SplashClip::clipToPath of the file splash/SplashClip.cc. Such manipulation leads to integer overflow. The attack can only be performed from a local environment.
Author: deepin-ci-robot <packages@deepin.org>
Origin: https://gitlab.freedesktop.org/poppler/poppler/-/commit/323c91036d99926a8b90dc14329f7b40aece22f8
Bug: https://nvd.nist.gov/vuln/detail/CVE-2026-102621
Last-Update: 2026-10-10
---
diff --git a/splash/SplashClip.cc b/splash/SplashClip.cc
index 0620c2c..9fc15a0 100644
--- a/splash/SplashClip.cc
+++ b/splash/SplashClip.cc
@@ -22,9 +22,12 @@

#include <config.h>

+#include <algorithm>
#include <cstdlib>
#include <cstring>
#include "goo/gmem.h"
+#include "goo/GooCheckedOps.h"
+#include "goo/GooLikely.h"
#include "SplashErrorCodes.h"
#include "SplashMath.h"
#include "SplashPath.h"
@@ -209,7 +212,9 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix, Splash
xPath.sort();
flags[length] = eo ? splashClipEO : 0;
if (antialias) {
- yMinAA = yMinI * splashAASize;
+ if (unlikely(checkedMultiply(yMinI, splashAASize, &yMinAA))) {
+ return splashErrGeneric;
+ }
yMaxAA = (yMaxI + 1) * splashAASize - 1;
} else {
yMinAA = yMinI;
172 changes: 172 additions & 0 deletions debian/patches/CVE-2026-107705.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
Description: CVE-2026-107705 (high) - Poppler 0.42.0 through 26.10.0 contains a stack-based buffer overflow in Decrypt::revision6Hash() that allows attackers controlling the password to overwrite stack memory when opening AESV3/R6 encrypted PDFs
Author: Albert Astals Cid <aacid@kde.org>
Origin: https://gitlab.freedesktop.org/poppler/poppler/-/merge_requests/2398.patch
Bug: https://security-tracker.debian.org/tracker/CVE-2026-107705
Last-Update: 2026-10-08
---
diff --git a/poppler/Decrypt.cc b/poppler/Decrypt.cc
index 5e72951..55b423e 100644
--- a/poppler/Decrypt.cc
+++ b/poppler/Decrypt.cc
@@ -54,16 +54,18 @@ static void sha256(unsigned char *msg, int msgLen, unsigned char *hash);
static void sha384(unsigned char *msg, int msgLen, unsigned char *hash);
static void sha512(unsigned char *msg, int msgLen, unsigned char *hash);

-static void revision6Hash(const GooString *inputPassword, unsigned char *K, const char *userKey);
+static void revision6Hash(const std::string &inputPassword, unsigned char *K, const char *userKey);

static const unsigned char passwordPad[32] = { 0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa, 0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe, 0x64, 0x53, 0x69, 0x7a };

+constexpr int kMaxPasswordLength = 127;
+
//------------------------------------------------------------------------
// Decrypt
//------------------------------------------------------------------------

bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const GooString *ownerKey, const GooString *userKey, const GooString *ownerEnc, const GooString *userEnc, int permissions, const GooString *fileID,
- const GooString *ownerPassword, const GooString *userPassword, unsigned char *fileKey, bool encryptMetadata, bool *ownerPasswordOk)
+ const GooString *ownerPasswordA, const GooString *userPasswordA, unsigned char *fileKey, bool encryptMetadata, bool *ownerPasswordOk)
{
DecryptAES256State state;
unsigned char test[127 + 56], test2[32];
@@ -71,20 +73,18 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
unsigned char fState[256];
unsigned char tmpKey[16];
unsigned char fx, fy;
- int len, i, j;
+ int i, j;

*ownerPasswordOk = false;

if (encRevision == 5 || encRevision == 6) {

// check the owner password
- if (ownerPassword) {
+ if (ownerPasswordA) {
//~ this is supposed to convert the password to UTF-8 using "SASLprep"
- len = ownerPassword->getLength();
- if (len > 127) {
- len = 127;
- }
- memcpy(test, ownerPassword->c_str(), len);
+ const std::string ownerPassword = ownerPasswordA->toStr().substr(0, kMaxPasswordLength);
+ const int len = ownerPassword.size();
+ memcpy(test, ownerPassword.c_str(), len);
memcpy(test + len, ownerKey->c_str() + 32, 8);
memcpy(test + len + 8, userKey->c_str(), 48);
sha256(test, len + 56, test);
@@ -95,7 +95,7 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
if (!memcmp(test, ownerKey->c_str(), 32)) {

// compute the file key from the owner password
- memcpy(test, ownerPassword->c_str(), len);
+ memcpy(test, ownerPassword.c_str(), len);
memcpy(test + len, ownerKey->c_str() + 40, 8);
memcpy(test + len + 8, userKey->c_str(), 48);
sha256(test, len + 56, test);
@@ -118,13 +118,11 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
}

// check the user password
- if (userPassword) {
+ if (userPasswordA) {
//~ this is supposed to convert the password to UTF-8 using "SASLprep"
- len = userPassword->getLength();
- if (len > 127) {
- len = 127;
- }
- memcpy(test, userPassword->c_str(), len);
+ const std::string userPassword = userPasswordA->toStr().substr(0, kMaxPasswordLength);
+ const int len = userPassword.size();
+ memcpy(test, userPassword.c_str(), len);
memcpy(test + len, userKey->c_str() + 32, 8);
sha256(test, len + 8, test);
if (encRevision == 6) {
@@ -135,7 +133,7 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
if (!memcmp(test, userKey->c_str(), 32)) {

// compute the file key from the user password
- memcpy(test, userPassword->c_str(), len);
+ memcpy(test, userPassword.c_str(), len);
memcpy(test + len, userKey->c_str() + 40, 8);
sha256(test, len + 8, test);
if (encRevision == 6) {
@@ -160,13 +158,13 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
} else {

// try using the supplied owner password to generate the user password
- if (ownerPassword) {
- len = ownerPassword->getLength();
+ if (ownerPasswordA) {
+ const int len = ownerPasswordA->getLength();
if (len < 32) {
- memcpy(test, ownerPassword->c_str(), len);
+ memcpy(test, ownerPasswordA->c_str(), len);
memcpy(test + len, passwordPad, 32 - len);
} else {
- memcpy(test, ownerPassword->c_str(), 32);
+ memcpy(test, ownerPasswordA->c_str(), 32);
}
md5(test, 32, test);
if (encRevision == 3) {
@@ -203,7 +201,7 @@ bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const
}

// try using the supplied user password
- return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, permissions, fileID, userPassword, fileKey, encryptMetadata);
+ return makeFileKey2(encVersion, encRevision, keyLength, ownerKey, userKey, permissions, fileID, userPasswordA, fileKey, encryptMetadata);
}
}

@@ -215,13 +213,13 @@ bool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, const
unsigned char fState[256];
unsigned char tmpKey[16];
unsigned char fx, fy;
- int len, i, j;
+ int i, j;
bool ok;

// generate file key
buf = (unsigned char *)gmalloc(72 + fileID->getLength());
if (userPassword) {
- len = userPassword->getLength();
+ const int len = userPassword->getLength();
if (len < 32) {
memcpy(buf, userPassword->c_str(), len);
memcpy(buf + len, passwordPad, 32 - len);
@@ -237,7 +235,7 @@ bool Decrypt::makeFileKey2(int encVersion, int encRevision, int keyLength, const
buf[66] = (permissions >> 16) & 0xff;
buf[67] = (permissions >> 24) & 0xff;
memcpy(buf + 68, fileID->c_str(), fileID->getLength());
- len = 68 + fileID->getLength();
+ int len = 68 + fileID->getLength();
if (!encryptMetadata) {
buf[len++] = 0xff;
buf[len++] = 0xff;
@@ -1756,7 +1754,7 @@ static void sha384(unsigned char *msg, int msgLen, unsigned char *hash)
// Section 7.6.3.3 (Encryption Key algorithm) of ISO/DIS 32000-2
// Algorithm 2.B:Computing a hash (for revision 6).
//------------------------------------------------------------------------
-static void revision6Hash(const GooString *inputPassword, unsigned char *K, const char *userKey)
+static void revision6Hash(const std::string &inputPassword, unsigned char *K, const char *userKey)
{
unsigned char K1[64 * (127 + 64 + 48)];
unsigned char E[64 * (127 + 64 + 48)];
@@ -1764,7 +1762,7 @@ static void revision6Hash(const GooString *inputPassword, unsigned char *K, cons
unsigned char aesKey[16];
unsigned char BE16byteNumber[16];

- int inputPasswordLength = inputPassword->getLength();
+ const int inputPasswordLength = inputPassword.size();
int KLength = 32;
const int userKeyLength = userKey ? 48 : 0;
int sequenceLength;
@@ -1775,7 +1773,7 @@ static void revision6Hash(const GooString *inputPassword, unsigned char *K, cons
sequenceLength = inputPasswordLength + KLength + userKeyLength;
totalLength = 64 * sequenceLength;
// a.make the string K1
- memcpy(K1, inputPassword->c_str(), inputPasswordLength);
+ memcpy(K1, inputPassword.c_str(), inputPasswordLength);
memcpy(K1 + inputPasswordLength, K, KLength);
if (userKey) {
memcpy(K1 + inputPasswordLength + KLength, userKey, userKeyLength);
19 changes: 19 additions & 0 deletions debian/patches/CVE-2026-93312.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Description: CVE-2026-93312 (medium) - 修复 poppler/JBIG2Stream.cc 中 pageBitmap 为 nullptr 时的崩溃问题
Author: Albert Astals Cid <aacid@kde.org>
Origin: https://gitlab.freedesktop.org/poppler/poppler/-/commit/5e49250f13b0390edeb3f90eb4c02c9941f97067.patch
Bug: https://nvd.nist.gov/vuln/detail/CVE-2026-93312
Last-Update: 2026-07-26
---
diff --git a/poppler/JBIG2Stream.cc b/poppler/JBIG2Stream.cc
index 990752a..97d64cc 100644
--- a/poppler/JBIG2Stream.cc
+++ b/poppler/JBIG2Stream.cc
@@ -1189,7 +1189,7 @@ void JBIG2Stream::reset()
mmrDecoder->setStream(curStr);
readSegments();

- if (pageBitmap) {
+ if (pageBitmap && pageBitmap->isOk()) {
dataPtr = pageBitmap->getDataPtr();
dataEnd = dataPtr + pageBitmap->getDataSize();
} else {
24 changes: 24 additions & 0 deletions debian/patches/CVE-2026-93313.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Description: CVE-2026-93313 (medium) - CVE-2026-93313 (medium) - 整数溢出漏洞在 JBIG2Stream::readCodeTableSeg 函数中 - 适配目标代码库 void 返回类型
Author: deepin-ci-robot <packages@deepin.org>
Origin: N/A
Bug: https://nvd.nist.gov/vuln/detail/CVE-2026-93313
Last-Update: 2026-10-08
---
diff --git a/poppler/JBIG2Stream.cc b/poppler/JBIG2Stream.cc
index 3c92e70..990752a 100644
--- a/poppler/JBIG2Stream.cc
+++ b/poppler/JBIG2Stream.cc
@@ -3962,7 +3962,12 @@ void JBIG2Stream::readCodeTableSeg(unsigned int segNum, unsigned int length)
goto oomError;
}
}
- huffTab[i].val = lowVal - 1;
+ int lowValMinusOne;
+ if (unlikely(checkedSubtraction(lowVal, 1, &lowValMinusOne))) {
+ free(huffTab);
+ return;
+ }
+ huffTab[i].val = lowValMinusOne;
huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
huffTab[i].rangeLen = jbig2HuffmanLOW;
++i;
36 changes: 36 additions & 0 deletions debian/patches/CVE-2026-93314.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Description: CVE-2026-93314 (medium) - FoFiTrueType::mapCodeToGID: Improve b*12 overflow check
Author: Albert Astals Cid <aacid@kde.org>
Origin: https://gitlab.freedesktop.org/poppler/poppler/-/commit/ed2a5538cf0a8d3ff908191eda9b73f91a5f952a
Bug: https://nvd.nist.gov/vuln/detail/CVE-2026-93314
Last-Update: 2026-07-26
---
diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc
index 020a374..71d8415 100644
--- a/fofi/FoFiTrueType.cc
+++ b/fofi/FoFiTrueType.cc
@@ -607,11 +607,15 @@ int FoFiTrueType::mapCodeToGID(int i, unsigned int c) const
gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
break;
case 12:
- case 13:
+ case 13: {
segCnt = getU32BE(pos + 12, &ok);
a = -1;
b = segCnt - 1;
- segEnd = getU32BE(pos + 16 + 12 * b + 4, &ok);
+ int b12;
+ if (checkedMultiply(b, 12, &b12)) {
+ return 0;
+ }
+ segEnd = getU32BE(pos + 16 + b12 + 4, &ok);
if (c > segEnd) {
return 0;
}
@@ -635,6 +639,7 @@ int FoFiTrueType::mapCodeToGID(int i, unsigned int c) const
// for an entire segment.
gid = segDelta + (cmaps[i].fmt == 12 ? (c - segStart) : 0);
break;
+ }
default:
return 0;
}
6 changes: 6 additions & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ CVE-2024-6239.patch
CVE-2025-43903.patch
CVE-2025-50420.patch
CVE-2025-52886.patch
CVE-2026-93314.patch
CVE-2026-93313.patch
CVE-2026-93312.patch
CVE-2026-107705.patch
CVE-2026-102621.patch
CVE-2026-102620.patch
Loading