Origin: upstream, https://code.qt.io/cgit/qt/qtbase.git/commit/?id=
647b221ca885739a
Last-Update: 2026-09-21
In both ~QDomNodePrivate() and QDomNodePrivate::clear(), the code
simply walked the list of chldren (->first, ->next), and deleted each
one in turn. This recurses into ~QDomNodePrivate() and uses stack
space proportional to the height of the tree. Since the latter is
user-controlled, this is a an easy DoS, so fix the implementation to
use iteration instead of recursion.
Note that it suffices to fix ~QDomNodePrivate(), as clear() only
recurses via the dtor, too.
Gbp-Pq: Name CVE-2026-19248.diff
QDomNodePrivate::~QDomNodePrivate()
{
- QDomNodePrivate* p = first;
- QDomNodePrivate* n;
-
- while (p) {
- n = p->next;
- if (!p->ref.deref())
- delete p;
- else
- p->setNoParent();
- p = n;
+ QDomNodePrivate *p = this;
+
+ // post-order depth-first-search; visitation is deletion (avoids recursion)
+ while (true) {
+ if (QDomNodePrivate *c = p->first) {
+ p->first = c->next; // peel firstChild off p
+ if (c->ref.deref())
+ c->setNoParent(); // survivor: detach, don't descend
+ else
+ p = c; // descend; c's parent() remembers p
+ } else { // p ran out of children (= is a leaf now)
+ if (p == this)
+ break; // we're done, don't `delete this`
+ delete std::exchange(p, p->parent()); // deletes and ascends
+ }
}
first = nullptr;
last = nullptr;