libicon: Fix dangling references to VertexSource in PathTransformer

PathTransformer keeps a reference to the VertexSource used (which can be
either another PathTransformer, or the base path for a shape). When a
shape is cloned, this should be retargetted to the new object in the
clone.

However, references are not settable, and so, what would happen instead
is the original (non-cloned) vertex source was reinitialized (through
the default implementation of the assignment operator) using data from
the clone, and the clone would still point to it. Then, if the original
object is deleted, the clone would point to freed memory.

To avoid this problem, replace the reference with a pointer (which can
be set to point elsewhere, as the code intended to do). To make sure
this does not happen again, make the VertexSource copy constructor and
assignment operator private, and deleted when the compiler supports
that.

Fixes #18577

Change-Id: I8870d9471c5064e922a84eff8447cbda783b13e6
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7052
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: Zardshard <0azrune6@zard.anonaddy.com>
This commit is contained in:
PulkoMandy 2023-10-17 16:04:51 +02:00 committed by Adrien Destugues
parent 51355272b3
commit 0822ec27a9
6 changed files with 28 additions and 17 deletions

View File

@ -27,6 +27,17 @@ class VertexSource {
/*! Determines whether open paths should be closed or left open. */
virtual bool WantsOpenPaths() const = 0;
virtual double ApproximationScale() const = 0;
private:
// Not allowed
#if __GNUC__ <= 2
#define NOT_ALLOWED
#else
#define NOT_ALLOWED = delete
#endif
VertexSource(const VertexSource& other) NOT_ALLOWED;
VertexSource& operator=(const VertexSource& other) NOT_ALLOWED;
#undef NOT_ALLOWED
};

View File

@ -61,7 +61,7 @@ AffineTransformer::~AffineTransformer()
Transformer*
AffineTransformer::Clone() const
{
AffineTransformer* clone = new (nothrow) AffineTransformer(fSource);
AffineTransformer* clone = new (nothrow) AffineTransformer(*fSource);
if (clone)
clone->multiply(*this);
return clone;
@ -93,7 +93,7 @@ AffineTransformer::SetSource(VertexSource& source)
double
AffineTransformer::ApproximationScale() const
{
return fabs(fSource.ApproximationScale() * scale());
return fabs(fSource->ApproximationScale() * scale());
}
// #pragma mark -

View File

@ -73,7 +73,7 @@ ContourTransformer::~ContourTransformer()
Transformer*
ContourTransformer::Clone() const
{
ContourTransformer* clone = new (nothrow) ContourTransformer(fSource);
ContourTransformer* clone = new (nothrow) ContourTransformer(*fSource);
if (clone) {
clone->line_join(line_join());
clone->inner_join(inner_join());
@ -111,7 +111,7 @@ ContourTransformer::SetSource(VertexSource& source)
double
ContourTransformer::ApproximationScale() const
{
double scale = fSource.ApproximationScale();
double scale = fSource->ApproximationScale();
double factor = fabs(width());
if (factor > 1.0)
scale *= factor;

View File

@ -24,25 +24,25 @@ class PathTransformer : public VertexSource
{
public:
PathTransformer(VertexSource& source)
: fSource(source) {}
: fSource(&source) {}
virtual ~PathTransformer() {}
// PathTransformer
virtual void rewind(unsigned path_id)
{ fSource.rewind(path_id); }
{ fSource->rewind(path_id); }
virtual unsigned vertex(double* x, double* y)
{ return fSource.vertex(x, y); }
{ return fSource->vertex(x, y); }
virtual void SetSource(VertexSource& source)
{ fSource = source; }
{ fSource = &source; }
virtual bool WantsOpenPaths() const
{ return fSource.WantsOpenPaths(); }
{ return fSource->WantsOpenPaths(); }
virtual double ApproximationScale() const
{ return fSource.ApproximationScale(); }
{ return fSource->ApproximationScale(); }
protected:
VertexSource& fSource;
VertexSource* fSource;
};

View File

@ -76,8 +76,8 @@ PerspectiveTransformer::PerspectiveTransformer(const PerspectiveTransformer& oth
#else
: Transformer(""),
#endif
PathTransformer(other.fSource),
Perspective(fSource, *this),
PathTransformer(*other.fSource),
Perspective(*fSource, *this),
fShape(other.fShape)
#ifdef ICON_O_MATIC
, fInverted(other.fInverted),
@ -162,7 +162,7 @@ PerspectiveTransformer::SetSource(VertexSource& source)
double
PerspectiveTransformer::ApproximationScale() const
{
return fSource.ApproximationScale() * scale();
return fSource->ApproximationScale() * scale();
}
@ -223,7 +223,7 @@ PerspectiveTransformer::ObjectChanged(const Observable* object)
uint32 pathID[1];
pathID[0] = 0;
double left, top, right, bottom;
agg::bounding_rect(fSource, pathID, 0, 1, &left, &top, &right, &bottom);
agg::bounding_rect(*fSource, pathID, 0, 1, &left, &top, &right, &bottom);
BRect newFromBox = BRect(left, top, right, bottom);
// Stop if nothing we care about has changed

View File

@ -76,7 +76,7 @@ StrokeTransformer::~StrokeTransformer()
Transformer*
StrokeTransformer::Clone() const
{
StrokeTransformer* clone = new (nothrow) StrokeTransformer(fSource);
StrokeTransformer* clone = new (nothrow) StrokeTransformer(*fSource);
if (clone) {
clone->line_cap(line_cap());
clone->line_join(line_join());
@ -122,7 +122,7 @@ StrokeTransformer::WantsOpenPaths() const
double
StrokeTransformer::ApproximationScale() const
{
double scale = fSource.ApproximationScale();
double scale = fSource->ApproximationScale();
double factor = fabs(width());
if (factor > 1.0)
scale *= factor;