Description:
------------
Condition: display_errors is off.
If you use imagecreatefromstring() with an invalid string, it returns a 500 Internal Server Error in the HTTP headers, but the page is fully renderized. It should return 200 OK (and the full page), or a 500 Error but without the full HTML. Not both at the same time.
5.3.10 and 5.4.44 are not affected.
5.5.9 and 5.6.12 are affected.
Test script:
---------------
<?php
ini_set("display_errors", 0);
$data = "iVBORw0KGgoAAAANSUhEUgAAAuwAAAUeCAYAAAAl3WR...LkAAAAAElFTkSuQmCC";
$data = base64_decode($data);
$im = imagecreatefromstring($data);
echo "This should not render";

History

> If you use imagecreatefromstring() with an invalid string, it
> returns a 500 Internal Server Error in the HTTP headers, […]
Indeed, that is not supposed to happen, and I can't reproduce it,
actually. Please double-check with any of the recent PHP versions
(5.5.36, 5.6.22, 7.0.7).

The header itself does not control the code execution.
The imagecreatefromstring returns false on error. That means the echo will happen.
It is the caller job to check the value and act accordingly. In case you expect the echo to never happen on error, that's not the case using this piece of code.

[2016-06-27 19:22 UTC] razzari at gmail dot com

@cmb can repro in PHP version 5.5.35.
@pajoye it's OK if the echo happens. The problem is that the page also includes an HTTP Error 500 header. Which is hugely wrong.

[2016-07-03 04:22 UTC] php-bugs at lists dot php dot net

No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.

Cmb cannot reproduce it.
Also I do not see the 500 header.
Doyou have either logs or backtrace if the 500 is due to something else?
In any case it is definitely not GD as everything goes aa expected from a gd point of view.

[2016-07-03 22:13 UTC] razzari at gmail dot com

This is still happening on PHP Version 5.6.23.
Screenshot: https://i.imgur.com/p680DMk.png
Note that BOTH the test text AND the 500 status code are displayed.
As noted by the OP, this only happens if display_errors is off.
If I enable errors, things work as expected. The error is displayed, and the page returns with a 200 OK status. Screenshot: https://i.imgur.com/8jyuiot.png
Compare this with standard platform behavior, where an error with display_errors off will produce a 500 error AND a blank page. It is NOT displaying the test text. Screenshot https://i.imgur.com/VCBOmun.png and sample code:
<?php
# This works as expected.
ini_set("display_errors", 0);
trigger_error("Some error.", E_USER_ERROR);
echo "This should not render";
?>
So to recap, expected behavior is:
Display errors OFF: Blank page, 500 status code.
Display errors ON: Visible error text, some page content that worked, and 200 status code.
Actual result in this situation is:
Display errors OFF: Some page content that worked, 500 status code.
Why this is a serious issue: site owners and visitors will believe the site is working OK. But Google will believe it's utterly broken and won't bother crawling it.

[2016-07-03 22:27 UTC] razzari at gmail dot com

Here's the logs as text (Sorry, I had included them in the screenshot in the prev comment).
PHP Unknown error: imagecreatefromstring(): gd-png: fatal libpng error: IHDR: CRC error\n in Unknown on line 0
PHP Parse error: imagecreatefromstring(): gd-png error: setjmp returns error condition 1\n in /var/www/test.php on line 6
PHP Warning: imagecreatefromstring(): Passed data is not in 'PNG' format in /var/www/test.php on line 6
PHP Warning: imagecreatefromstring(): Couldn't create GD Image Stream out of Data in /var/www/test.php on line 6
I can repro this consistently.
Please let me know if I can provide further info/tests.
This is a barebones install in Ubuntu 12.04, Apache/2.4.2, PHP 5.6.23-2+deb.sury.org~precise+1. I've just installed this in a Vagrant box for testing. (That is, this isn't a prod server with weird configs or a dev server wit cruft that's piled up over the years).

Okay, I'am able to reproduce the reported behavior now. It happens
only when an external libgd is used, not with PHP's bundled libgd.
> PHP Unknown error: imagecreatefromstring(): gd-png: fatal […]
> PHP Parse error: imagecreatefromstring(): gd-png error: […]
That's the crux. The bundled libgd reports instead:
| Warning: imagecreatefromstring(): gd-png: fatal […]
| Warning: imagecreatefromstring(): gd-png error: […]
One culprit is php_gd_error_method()[1] which simply forwards to
php_verror() without adjusting the type argument, although libgd
uses other error codes than PHP (for instance, GD_ERROR is 3,
which is unknown to PHP). While a simple mapping of the error
codes would solve this problem, it still would cause different
behavior depending whether the bundled or an external libgd is
used. In this case the bundled libgd would raise warnings only and
simply go on, while an external libgd would raise errors and abort
the script.
As changing libgd obviously isn't an option due to the ABI break,
we probably should change PHP's bundled libgd (i.e. raise E_ERROR
instead of E_WARNING), but that would cause a BC break, so maybe
it's best to do that only for PHP 7.1.0, and to accept the
different behavior for older versions. php_gd_error_method(),
however, should be fixed for PHP 5.6+.
I'll prepare a PR.
[1] <https://github.com/php/php-src/blob/php-7.0.8/ext/gd/gd.c#L1021-L1025>

I'm not familiar with PHP internals. Not at all.
But have to ask.
Feel free to ignore if it's a dumb question:
Isn't it a more general bug, at the architecture level, that an "unknown" error code can cause PHP to render pages in a half-broken state?
Where "half-broken" is the worst kind: looks good to the naked eye, but rejects search engine crawlers.

> Isn't it a more general bug, at the architecture level, that an
> "unknown" error code can cause PHP to render pages in a
> half-broken state?
In my opinion, passing unknown error codes is a programmer error
(core or extension), and should be reported (and fixed) as bug on
a case-by-case basis (like this one).