Coordinated Disclosure Timeline
- 2025-04-03: Reported as a private issue: https://gitlab.freedesktop.org/poppler/poppler/-/issues/1580
- 2025-09-03: Created a merge request with our suggested fix: https://gitlab.freedesktop.org/poppler/poppler/-/merge_requests/1884
- 2025-29-09: Fixed merged https://gitlab.freedesktop.org/poppler/poppler/-/merge_requests/1884#note_3114334
Summary
A use-after-free (write) vulnerability has been detected in Poppler within the StructTreeRoot class. The issue arises from the use of raw pointers to elements of a std::vector, which can lead to dangling pointers when the vector is resized.
Project
poppler
Tested Version
25.02.0
Details
Use-After-Free (write) in StructTreeRoot::parentTreeAdd (GHSL-2025-042)
The vulnerability stems from the way that refToParentMap stores references to std::vector elements using raw pointers. These pointers may become invalid when the vector is resized.
This vulnerability is a common security problem involving the use of raw pointers to std::vectors. Internally, std::vector stores its elements in a dynamically allocated array. When the array reaches its capacity and a new element is added, the vector reallocates a larger block of memory and moves all the existing elements to the new location. At this point if any pointers to elements are stored before a resize occurs, they become dangling pointers once the reallocation happens.
The affected method is StructTreeRoot::parseNumberTreeNode in the file poppler/StructTreeRoot.c, and specifically, the following code snippet:
int keyVal = key.getInt();
std::vector<Parent> &vec = parentTree[keyVal]; //Get the vector reference
...
vec.resize(valueArray.arrayGetLength()); //vector resize (and posible new allocation) happens
...
refToParentMap.insert(std::pair<Ref, Parent *>(ref, &vec[j])); //inserts a reference to 'vec' into the std::multimap
In this code snippet, a pointer to an element of vec is inserted into refToParentMap (see line 149). However, in subsequent iterations the vector may be resized (as seen on line 143), which frees the previously allocated memory and allocates new memory. As a result, the old pointer remains in refToParentMap and becomes a dangling pointer.
Impact
It’s possible that this use-after-free bug could be exploited to achieve code execution in poppler.
CWEs
- CWE-416: “Use After Free”
CVE
- CVE-2025-52885
Credit
This issue was discovered and reported by GHSL team member @antonio-morales (Antonio Morales).
Contact
You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2025-042 in any communication regarding this issue.