PDF: Fix memory leak when the file has Optional Content links

This commit is contained in:
Albert Astals Cid 2021-12-29 09:55:56 +01:00
parent 3400e8aee6
commit e2ac1dcd1e
9 changed files with 73 additions and 0 deletions

View file

@ -2513,6 +2513,37 @@ void Document::closeDocument()
// close the current document and save document info if a document is still opened
if (d->m_generator && d->m_pagesVector.size() > 0) {
d->saveDocumentInfo();
// free the content of the opaque backend actions (if any)
// this is a bit awkward since backends can store "random stuff" in the
// BackendOpaqueAction nativeId qvariant so we need to tell them to free it
// ideally we would just do that in the BackendOpaqueAction destructor
// but that's too late in the cleanup process, i.e. the generator has already closed its document
// and the document generator is nullptr
for (Page *p : qAsConst(d->m_pagesVector)) {
const QLinkedList<ObjectRect *> &oRects = p->objectRects();
for (ObjectRect *oRect : oRects) {
if (oRect->objectType() == ObjectRect::Action) {
const Action *a = static_cast<const Action *>(oRect->object());
const BackendOpaqueAction *backendAction = dynamic_cast<const BackendOpaqueAction *>(a);
if (backendAction) {
d->m_generator->freeOpaqueActionContents(*backendAction);
}
}
}
const QLinkedList<FormField *> forms = p->formFields();
for (const FormField *form : forms) {
const QList<Action *> additionalActions = form->additionalActions();
for (const Action *a : additionalActions) {
const BackendOpaqueAction *backendAction = dynamic_cast<const BackendOpaqueAction *>(a);
if (backendAction) {
d->m_generator->freeOpaqueActionContents(*backendAction);
}
}
}
}
d->m_generator->closeDocument();
}

View file

@ -115,6 +115,13 @@ void FormField::setAdditionalAction(Annotation::AdditionalActionType type, Actio
d->m_additionalAnnotActions[type] = action;
}
QList<Action *> FormField::additionalActions() const
{
Q_D(const FormField);
// yes, calling values() is not great but it's a list of ~10 elements, we can live with that
return d->m_additionalAnnotActions.values() + d->m_additionalActions.values(); // clazy:exclude=container-anti-pattern
}
class Okular::FormFieldButtonPrivate : public Okular::FormFieldPrivate
{
public:

View file

@ -157,6 +157,12 @@ public:
*/
Action *additionalAction(Annotation::AdditionalActionType type) const;
/* Returns all the additional actions for this form
*
* @since 22.04
*/
QList<Action *> additionalActions() const;
protected:
/// @cond PRIVATE
explicit FormField(FormFieldPrivate &dd);

View file

@ -386,6 +386,10 @@ void Generator::opaqueAction(const BackendOpaqueAction * /*action*/)
{
}
void Generator::freeOpaqueActionContents(const BackendOpaqueAction & /*action*/)
{
}
QVariant Generator::metaData(const QString &key, const QVariant &option) const
{
Q_D(const Generator);

View file

@ -451,6 +451,13 @@ public:
*/
virtual void opaqueAction(const BackendOpaqueAction *action);
/**
* Frees the contents of the opaque action (if any);
*
* @since 22.04
*/
virtual void freeOpaqueActionContents(const BackendOpaqueAction &action);
Q_SIGNALS:
/**
* This signal should be emitted whenever an error occurred in the generator.

View file

@ -582,6 +582,11 @@ void Page::setObjectRects(const QLinkedList<ObjectRect *> &rects)
m_rects << rects;
}
const QLinkedList<ObjectRect *> &Page::objectRects() const
{
return m_rects;
}
void PagePrivate::setHighlight(int s_id, RegularAreaRect *rect, const QColor &color)
{
HighlightAreaRect *hr = new HighlightAreaRect(rect);

View file

@ -283,6 +283,13 @@ public:
*/
void setObjectRects(const QLinkedList<ObjectRect *> &rects);
/**
* Gets the list of object rects of the page.
*
* @since 22.04
*/
const QLinkedList<ObjectRect *> &objectRects() const;
/**
* Sets the list of source reference objects @p rects.
*/

View file

@ -1008,6 +1008,11 @@ void PDFGenerator::opaqueAction(const Okular::BackendOpaqueAction *action)
pdfdoc->optionalContentModel()->applyLink(const_cast<Poppler::LinkOCGState *>(popplerLink));
}
void PDFGenerator::freeOpaqueActionContents(const Okular::BackendOpaqueAction &action)
{
delete action.nativeId().value<const Poppler::LinkOCGState *>();
}
bool PDFGenerator::isAllowed(Okular::Permission permission) const
{
bool b = true;

View file

@ -71,6 +71,7 @@ public:
}
QAbstractItemModel *layersModel() const override;
void opaqueAction(const Okular::BackendOpaqueAction *action) override;
void freeOpaqueActionContents(const Okular::BackendOpaqueAction &action) override;
// [INHERITED] document information
bool isAllowed(Okular::Permission permission) const override;