imagecreatefrompng (and imagecreatefromstring) causes to unrecoverable fatal error
Asked Answered
M

3

6

When I'm trying use php-gd functions on incorrect png images, I have Fatal PHP error. It seems to be some kind of bug, because accordingly to the functions documentation (imagecreatefrompng, for example):

* @return resource an image resource identifier on success, false on errors.

But when I try to do it with my incorrect image, I have:

Fatal error: imagecreatefrompng(): gd-png: fatal libpng error: Read Error: truncated data in /var/www/common/models/Utils.php on line 61

The code that leads to this error is simple:

$handle = imagecreatefrompng($fname);

No code executes after this string.

The same behaviour is for imagecreatefromstring when trying to create an image from the same string.

I can't "fix" this picture, because it is user-provided, so I need to handle this cases.

I tried to use try...catch block like this:

echo 'start'."\n";
try {
    imagecreatefromstring($result);
} catch (\Throwable $e) {
    echo 'error'."\n";
    return null;
}
echo 'success'."\n";

But script outputs only "start", and then dies and shows error description I have posted above.

Ubuntu 16.04.2, PHP 7.0, php7.0-gd extension, both are latest version.

So I can't handle it with try...catch block and I don't know how to handle or fix it at all. Any ideas?

UPD: It seems to be really weird bug with environment, because when I run same code under Windows (with PHP 7.0) it produces correct "Warning" error.

UPD2: It seems to be that fresh bug https://bugs.php.net/bug.php?id=73986

Morey answered 18/7, 2017 at 18:41 Comment(5)
Maybe this will help you (the png is corrupted) #41338701Ruby
@Ruby thanks for comment. But in question you give the guy receive "Warning" error which can be easily handled. In my case I have fatal error, so things becomes harder to handle.Morey
But the problem is the error you are having, your PNG seems to be corrupted, can you make sure that your PNGs are not corrupted by opening those ? Search the Fatal error, you will find a lot of information.Ruby
@Ruby I must check this file for corruptness using PHP. This picture is provided by user and I have not idea how to check it for corruptness. If I use getimagesize for such check, it returns correct values (shows mime type and sizes). Do you know any other ways to check image?Morey
Updated question and my answer with possible reason: it's bug. Thank you for help.Morey
D
5

A bit late to the party, but i ran into this problem as well, and cannot wait for the bug fix to be included in my ubuntu LTS The only clean workaround i found is actually to use Imagick::valid() check the image is valid.

function imageIsValid($path)
{
    try
    {
        $imagick = new \Imagick($path);

        return $imagick->valid();
    }
    catch (\Exception $e)
    {
        return false;
    }
}

Of course, your server/hosting needs to have php imagick extension installed...

Duero answered 22/1, 2018 at 16:55 Comment(1)
Thank you for sharing another approach!Morey
M
1

It seems to be fresh bug (and possibly not closed): https://bugs.php.net/bug.php?id=73986

So until I will find better way, I think it is only one way to check image. It is BAD code and i know it, but I have no other ideas. The idea is to try create an image in another thread and return check value depends on it's output.

$fname = tempnam('/tmp', 'test_');
$handle = fopen($fname, 'w');
fwrite($handle, $result);
fclose($handle);

$output = `php -r "imagecreatefrompng('$fname');" 2>&1`;
unlink($fname);

if (!empty($output)) {
    return null; // error
}
// good image

Backtrick operator will execute command in shell. Than it will output error to stderr. 2>&1 used to make stderr stream output to stdout stream so it can be accessed via backtrick operator.

Morey answered 18/7, 2017 at 19:36 Comment(1)
NO NO NO NO NO!!!!! This is a trivially exploitable remote code execution vulnerability.Lingle
B
0

Since PHP7 all errors are exceptions so you can simply wrap fragile code part inside try-catch block to catch the \Throwable exception and handle accordingly.

Baziotes answered 18/7, 2017 at 19:42 Comment(4)
thank you for suggestion, but in my case, when I wrap this part of code with try{...code...}catch(\Throwable $e){...echo...} no echo is performed. Script just dies with error message shown in stderr. It seems to be some kind of non-recoverable errors or something like that. What type of errors can cause to such behaviour?Morey
I updated my question with exactly code I used for checkMorey
Updated question and my answer with possible reason: it's bug. Thank you for help.Morey
We are running PHP7 and prefixing function with @ yet the error is fatal :/Kreg

© 2022 - 2024 — McMap. All rights reserved.