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

SeRRgIO
  • 167
  • 2
  • 12
  • Maybe this will help you (the png is corrupted) https://stackoverflow.com/questions/41338201/fix-corrupt-png-truncated-data-in-php – matiaslauriti Jul 18 '17 at 18:44
  • @matiaslauriti 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. – SeRRgIO Jul 18 '17 at 18:46
  • 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. – matiaslauriti Jul 18 '17 at 18:48
  • @matiaslauriti 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? – SeRRgIO Jul 18 '17 at 18:51
  • Updated question and my answer with possible reason: it's bug. Thank you for help. – SeRRgIO Jul 18 '17 at 20:40

3 Answers3

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...

JulienV
  • 775
  • 7
  • 12
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.

SeRRgIO
  • 167
  • 2
  • 12
  • 4
    NO NO NO NO NO!!!!! This is a trivially exploitable remote code execution vulnerability. – Demi Nov 04 '18 at 23:57
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.

Mike Doe
  • 16,349
  • 11
  • 65
  • 88
  • 1
    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? – SeRRgIO Jul 18 '17 at 19:55
  • I updated my question with exactly code I used for check – SeRRgIO Jul 18 '17 at 20:01
  • Updated question and my answer with possible reason: it's bug. Thank you for help. – SeRRgIO Jul 18 '17 at 20:40
  • 2
    We are running PHP7 and prefixing function with `@` yet the error is fatal :/ – rayrutjes Oct 18 '17 at 15:02