imagesettile() and imagesetbrush() keep a dangling pointer once the tile is freed

Ouverte
#25,334 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Cette issue n'a pas encore été évaluée.

Description

Description

imagesettile() passes the libgd pointer of the tile to gdImageSetTile() without keeping a reference to the tile object. Once the tile GdImage is freed, the image keeps a dangling pointer, and the next fill with IMG_COLOR_TILED reads freed memory. imagesetbrush() has the same shape, with IMG_COLOR_BRUSHED.

The following code:

<?php
$canvas = imagecreatetruecolor(100, 100);
(function () use ($canvas) {
    $tile = imagecreatetruecolor(10, 10);
    imagesettile($canvas, $tile);
})();
// The tile is freed: its memory is reused
$strings = [];
for ($i = 0; $i < 10000; ++$i) {
    $strings[] = str_repeat("\xff", 7000 + $i % 64);
}
imagefilledrectangle($canvas, 0, 0, 99, 99, IMG_COLOR_TILED);
echo "survived\n";

Resulted in this output:

Segmentation fault

But I expected this output instead:

survived

It crashes every time on PHP 8.5.12 (macOS, system libgd 2.3.3) and on PHP 8.4.27 (the php:8.4-cli Docker image, bundled GD). The same script with imagesetbrush() and imageline(..., IMG_COLOR_BRUSHED) also crashes on 8.5.12.

In ext/gd/gd.c on master, PHP_FUNCTION(imagesettile) and PHP_FUNCTION(imagesetbrush) only call gdImageSetTile(im, tile) and gdImageSetBrush(im, tile), and php_gd_image_object has no field that would hold the tile or the brush. A fix could keep a reference to the tile and brush objects in php_gd_image_object, released when they are replaced and when the image is freed (and reported by get_gc).

I found it while drawing SVG patterns with GD in a userland library: keeping the tile in a variable until the drawing ends works around it.

PHP Version
PHP 8.5.12 (cli) (ZTS)
PHP 8.4.27 (cli) (php:8.4-cli Docker image)
Operating System

macOS 27; Debian (Docker)

Langage dominant
C
Étoiles
41.8k
Forks
8.5k
Merge moyen
2 j 12 h
PR mergées (30 j)
137

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de php/php-src

Toutes les issues de php/php-src

Issues similaires

Plus d'issues C

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.