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

オープン
#25,334 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

この issue はまだ評価されていません。

説明

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)

主要言語
C
スター
41.8k
フォーク
8.5k
平均マージ
2日 12時間
マージ済み PR(30日)
137

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

php/php-src のほかの issue

php/php-src の issue をすべて見る

似ている issue

C の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。