Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX 5284: Prevent crash for lager images. #2569

Closed
wants to merge 2 commits into from

Conversation

jakr
Copy link
Contributor

@jakr jakr commented Oct 20, 2013

Implemented check in GD that estimates the memory required to load the image and rejects larger images. Created lock files that remains after a large image has previously crashed GD.

Implemented check in GD that estimates the memory required to load the image and rejects larger images. Created lock files that remains after a large image has previously crashed GD.
@jakr
Copy link
Contributor Author

jakr commented Oct 20, 2013

This is the result of the discussion in the mailinglist and on the previous commit jakr@344a464. Thanks to all who participated!

This fixes the problem, but I am still a bit concerned that it might need some refactoring - currently we have to know the convention in for the lock file name in three places: GD (where it is generated), Image (so that it is removed upon deletion) and the test (so that we can check if it works). This seems hacky to me.
Unfortunately, I currently do not know how else to do it, one idea would be to introduce a method getLockfileName() into Image_Backend, but I don't want to clutter the interface.

Despite these concerns, I think the benefit of fixing this overweight the problems of the solution.

@wilr FYI: This is an updated version of the patch in http://open.silverstripe.org/ticket/5284. I don't know if you can or want to link this pull request to the old tracker.

public function __construct($filename = null) {
// Check for _lock file, if it exists we crashed while opening this file --> do not try again
if(file_exists(self::get_lockfile_name($filename)) || !self::image_fits_available_memory($filename)) return;
fclose(fopen(self::get_lockfile_name($filename), 'w')); //create .lock file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using touch() looks much cleaner than this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, thanks. Did not know that touch was available in php.

@simonwelsh
Copy link
Contributor

I'm concerned that this has one lock per image. Why should being unable to create a large image prevent you from creating a thumbnail? (Say, $SetWidth(2000) fails due to the second buffer, I would expect $SetSize(50,50) to still work)

@jakr
Copy link
Contributor Author

jakr commented Oct 20, 2013

I think that these just not right (anti-goldilock) images are a rare edge case. I came across the problem that an image was so large (and memory_limit so low) that not even a small thumbnail could be created.
If your image failed in large sizes, the only way to find out about it is reading the log or getting customer complaints. With the lock file, the backend could in principle display a warning instead of that image (or something similar), so that the user knows that an image has a problem.
Lastly, if you made the lock file size specific, for a much too large file you would crash once for every size. I don't think that's a better behavior :-).

@kinglozzer
Copy link
Member

@dhensby and I had a few comments on this pull request that we left in the mailing list: https://groups.google.com/forum/#!topic/silverstripe-dev/B57a3KYeAVQ.

They mainly discussed making sure we don't leave any code in Image or Image_Backend that's specific to GD and this issue - if a developer uses a different Image_Backend implementation then these memory checks may not apply.

An example is the changes to Image->onBeforeDelete() in this pull request - the behaviour of searching for a lock file and deleting it is specific to GD only.

@jakr
Copy link
Contributor Author

jakr commented Oct 24, 2013

I read your comments and agree. In my opinion the cleanest way to do this would be to add onBeforeDelete to Image_Backend and to move the deletion code down to GD. Image then would pass on the onBeforeDelete to the backend. Of course the test cases would also move to GD. I'll try to write something up over the weekend and create a new pull.

@jakr jakr closed this Oct 24, 2013
chillu added a commit to open-sausages/silverstripe-framework that referenced this pull request Jan 6, 2017
This was removed as part of the SS4 assets refactor:
silverstripe@be23989
Presumably @tractorcow didn’t feel it’s possible to retain this,
because we don’t have local file handles required for getimagesize().
Since there’s getimagesizefromstring() as well (added in PHP 5.4),
we just needed a different logic branch.

Also makes the logic more resilient against missing GD resources on a backend.
Lack of available memory for a resize is only one (new) reason,
other edge cases were already causing these missing resources (e.g. an invalid file string).

Original discussion: https://groups.google.com/forum/m/#!topic/silverstripe-dev/B57a3KYeAVQ
Pull request for 3.x: silverstripe#2859
More context: silverstripe#2569
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants