File poppler-CVE-2025-11896.patch of Package poppler.41938
From 998c6a79571af968ba90af57a0c5dcbb5a53763c Mon Sep 17 00:00:00 2001
From: Sune Vuorela <sune@vuorela.dk>
Date: Mon, 13 Oct 2025 15:13:14 +0200
Subject: [PATCH] Limit recursion in cmap parsing
fixes #1632
---
poppler/CMap.cc | 18 +++++++++++-------
poppler/CMap.h | 13 +++++++------
2 files changed, 18 insertions(+), 13 deletions(-)
Index: poppler-0.79.0/poppler/CMap.cc
===================================================================
--- poppler-0.79.0.orig/poppler/CMap.cc
+++ poppler-0.79.0/poppler/CMap.cc
@@ -62,7 +62,7 @@ static int getCharFromStream(void *data)
//------------------------------------------------------------------------
-CMap *CMap::parse(CMapCache *cache, const GooString *collectionA, Object *obj) {
+CMap *CMap::parse(CMapCache *cache, const GooString *collectionA, Object *obj, int recursion) {
CMap *cMap;
GooString *cMapNameA;
@@ -75,7 +75,7 @@ CMap *CMap::parse(CMapCache *cache, cons
}
delete cMapNameA;
} else if (obj->isStream()) {
- if (!(cMap = CMap::parse(nullptr, collectionA, obj->getStream()))) {
+ if (!(cMap = CMap::parse(nullptr, collectionA, obj->getStream(), recursion + 1))) {
error(errSyntaxError, -1, "Invalid CMap in Type 0 font");
}
} else {
@@ -114,11 +114,15 @@ CMap *CMap::parse(CMapCache *cache, cons
return cMap;
}
-CMap *CMap::parse(CMapCache *cache, const GooString *collectionA, Stream *str) {
+CMap *CMap::parse(CMapCache *cache, const GooString *collectionA, Stream *str, int recursion)
+{
+ if (recursion > 50) {
+ return nullptr;
+ }
CMap *cMap = new CMap(collectionA->copy(), nullptr);
Object obj1 = str->getDict()->lookup("UseCMap");
if (!obj1.isNull()) {
- cMap->useCMap(cache, &obj1);
+ cMap->useCMap(cache, &obj1, recursion);
}
str->reset();
@@ -347,10 +351,10 @@ void CMap::useCMap(CMapCache *cache, cha
subCMap->decRefCnt();
}
-void CMap::useCMap(CMapCache *cache, Object *obj) {
+void CMap::useCMap(CMapCache *cache, Object *obj, int recursion) {
CMap *subCMap;
- subCMap = CMap::parse(cache, collection, obj);
+ subCMap = CMap::parse(cache, collection, obj, recursion + 1);
if (!subCMap) {
return;
}
Index: poppler-0.79.0/poppler/CMap.h
===================================================================
--- poppler-0.79.0.orig/poppler/CMap.h
+++ poppler-0.79.0/poppler/CMap.h
@@ -28,6 +28,7 @@
#include <atomic>
+#include "Object.h"
#include "poppler-config.h"
#include "CharTypes.h"
@@ -44,7 +45,7 @@ public:
// Parse a CMap from <obj>, which can be a name or a stream. Sets
// the initial reference count to 1. Returns NULL on failure.
- static CMap *parse(CMapCache *cache, const GooString *collectionA, Object *obj);
+ static CMap *parse(CMapCache *cache, const GooString *collectionA, Object *obj, int recursion = 0);
// Create the CMap specified by <collection> and <cMapName>. Sets
// the initial reference count to 1. Returns NULL on failure.
@@ -53,7 +54,7 @@ public:
// Parse a CMap from <str>. Sets the initial reference count to 1.
// Returns NULL on failure.
- static CMap *parse(CMapCache *cache, const GooString *collectionA, Stream *str);
+ static CMap *parse(CMapCache *cache, const GooString *collectionA, Stream *str, int recursion);
// Create the CMap specified by <collection> and <cMapName>. Sets
// the initial reference count to 1.
@@ -96,7 +97,7 @@ private:
CMap(GooString *collectionA, GooString *cMapNameA);
CMap(GooString *collectionA, GooString *cMapNameA, int wModeA);
void useCMap(CMapCache *cache, char *useName);
- void useCMap(CMapCache *cache, Object *obj);
+ void useCMap(CMapCache *cache, Object *obj, int recursion);
void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src);
void addCIDs(unsigned int start, unsigned int end, unsigned int nBytes, CID firstCID);
void freeCMapVector(CMapVectorEntry *vec);