iOS - Random crash in CoreGraphicsPixelData::createImage

Hi All,

My JUCE iOS app is crashing randomly in CoreGraphicsPixelData::createImage. I have created a custom class ResizableImageLabel which will draw a background image and text. Drawing of background image will be done in separate class ResizableImage.

class ResizableImageLabel : public Label
{
public:
    ResizableImageLabel(const String& name)
    :   Label(name, name)
    {
        setJustificationType(Justification::centred);
        setFont(Font(25));
        setColour(Label::backgroundColourId, Colours::transparentBlack);
    }
    
    void paint(Graphics& g) override
    {
        auto rect = getLocalBounds();
        _backgroundImage.drawInRect(g, rect);
        g.setColour(Colours::white);
        g.drawText(getText(), rect, Justification::centred);
    }
    
    ResizableImage _backgroundImage;
};

And the code snippet for the ResizableImage Drawing code is as below:

void ResizableImage::drawInRect(const juce::Graphics &g, int x, int y, int width, int height) const
{
    jassert(_image.isValid());
    
    if (!(width > 0 && height > 0))
    {
        return;
    }
    
    if (resizeMode == ResizeMode::DontResize || _imageInsets.isZero())
    {
        // Draw image as normal and return
        g.drawImageWithin(_image,
                          x, y, width, height,
                          RectanglePlacement::stretchToFit);
        return;
    }
    
    int leftInset = _imageInsets.leftInset / _imageInsets.overscalingFactor;
    int rightInset = _imageInsets.rightInset / _imageInsets.overscalingFactor;
    int topInset = _imageInsets.topInset / _imageInsets.overscalingFactor;
    int bottomInset = _imageInsets.bottomInset / _imageInsets.overscalingFactor;
    
    int imageWidth = _image.getWidth();
    int imageHeight = _image.getHeight();
    int centreWidth = width - leftInset - rightInset;
    int centreHeight = height - topInset - bottomInset;
    
    int imageCentreWidth = imageWidth - _imageInsets.leftInset - _imageInsets.rightInset;
    int imageCentreHeight = imageHeight - _imageInsets.topInset - _imageInsets.bottomInset;
    
    // ============================== Draw Centre ==============================
    if (centreWidth > 0 && centreHeight > 0)
    {
        switch (resizeMode)
        {
            case OnlyDrawOutside:
                break;
                
            case StretchInsde:
                g.drawImage(_image,
                            x + leftInset,
                            y + topInset,
                            centreWidth,
                            centreHeight,
                            _imageInsets.leftInset,
                            _imageInsets.topInset,
                            imageCentreWidth,
                            imageCentreHeight);
                break;
        }
    }

To simulate the same issue, I have created Test App with only ResizableImageLabel and enabled address sanitizer. I am observing the same behaviour(JUCE Message Thread (1): Heap buffer overflow). Also attached TestApp project. I am using JUCE 6.1.4, MacOS-12.1 and iOS-15.2

I am unable to figure out the issue. Could you please help?

TestApp.zip (77.4 KB)

Thanks in advance.

Hi All,

Another observation is that same code is working fine in the following scenarios.

  1. Replace drawImage function with drawImageWithin
  2. Replace drawImage function with drawImageAt
  3. Replace drawImage function parameters with fixed values(Very weird) like below
                g.drawImage(_image,
                            x + leftInset,
                            y + topInset,
                            centreWidth,
                            centreHeight,
                            _imageInsets.leftInset,
                            _imageInsets.topInset,
                            imageCentreWidth,
                            imageCentreHeight);
changed to 
                g.drawImage(_image,
                            x,
                            y,
                            centreWidth,
                            centreHeight,
                            0,
                            0,
                            imageCentreWidth,
                            imageCentreHeight);

Also verified that same code is working fine with JUCE4.3.1.
ResizableImageLabel.cpp (7.6 KB)
ResizableImageLabel.h (1.7 KB)

Thanks for reporting. I think the crash is due to an incorrect image buffer size calculation when copying an image subsection to a CFData instance. I’m working on a fix, which I hope to merge shortly.

1 Like

Would this fix affect the macOS version too? I’m pretty sure I’ve seen the odd crash report from users similar to this. This feels familiar.

The problem is in some code shared between macOS and iOS, so it’s likely to be an issue on both platforms, yes.

Thank you @reuk.

Hi @reuk, Any update on the fix(When can we expect the merge)? Thank you.

HI @reuk ,

I have also seen some random crash on this. I could not narrow it down further.

Can you please share the quick fix? Or a commit which I can cherry pick?

Best Regards,
DSouza

The fix is still awaiting review. I expect it to be merged later this week.

1 Like

The fix has now been merged:

Please try updating and let us know if you discover any new issues.

2 Likes

That seems to be working fine. Thank you @reuk.