Commit 5dd39094226 for php.net

commit 5dd39094226e9dffe7a59fc70f60032751eae66e
Author: David Carlier <devnexen@gmail.com>
Date:   Fri May 22 06:15:44 2026 +0100

    Fix GH-19739: imageellipse/imagefilledellipse overflow.

    Port the upstream libgd portable fix (overflowMul3) for the int64
    overflow at r = a * bq when w/h reach near INT_MAX. Mirrors the
    upstream libgd commit 0057de6.

    close GH-22116

diff --git a/NEWS b/NEWS
index db03aa98c3a..3899aea32ca 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP                                                                        NEWS
     overflow-triggered early return). (iliaal)
   . Fixed bug GH-19666 (imageconvolution() unexpected nan filter value).
     (David Carlier)
+  . Fixed bug GH-19739 (imageellipse/imagefilledellipse overflow).
+    (David Carlier)

 - Intl:
   . Fix incorrect argument positions for uninitialized calendar arguments in
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index 0ab26647c1d..7a2692436a1 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -1775,6 +1775,9 @@ void gdImageEllipse(gdImagePtr im, int mx, int my, int w, int h, int c)

 	a=w>>1;
 	b=h>>1;
+	if (overflowMul3(a, b, b) || overflowMul3(b, a, a)) {
+		return;
+	}
 	gdImageSetPixel(im,mx+a, my, c);
 	gdImageSetPixel(im,mx-a, my, c);
 	mx1 = mx-a;my1 = my;
@@ -1816,7 +1819,9 @@ void gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c)

 	a=w>>1;
 	b=h>>1;
-
+	if (overflowMul3(a, b, b) || overflowMul3(b, a, a)) {
+		return;
+	}
 	for (x = mx-a; x <= mx+a; x++) {
 		gdImageSetPixel(im, x, my, c);
 	}
diff --git a/ext/gd/libgd/gd_security.c b/ext/gd/libgd/gd_security.c
index 438a564ff17..cbc4872d2fc 100644
--- a/ext/gd/libgd/gd_security.c
+++ b/ext/gd/libgd/gd_security.c
@@ -14,6 +14,7 @@

 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <limits.h>
 #include "gd.h"
 #include "gd_errors.h"
@@ -30,3 +31,20 @@ int overflow2(int a, int b)
 	}
 	return 0;
 }
+
+int overflowMul3(int a, int b, int c)
+{
+	if (a < 0 || b < 0 || c < 0) {
+		return 1;
+	}
+	if (a == 0 || b == 0 || c == 0) {
+		return 0;
+	}
+	if (a > INT_MAX / b) {
+		return 1;
+	}
+	if ((int64_t)a * b > INT64_MAX / c) {
+		return 1;
+	}
+	return 0;
+}
diff --git a/ext/gd/libgd/gdhelpers.h b/ext/gd/libgd/gdhelpers.h
index afb45f0e67d..202ccfce763 100644
--- a/ext/gd/libgd/gdhelpers.h
+++ b/ext/gd/libgd/gdhelpers.h
@@ -27,6 +27,7 @@ extern char *gd_strtok_r(char *s, char *sep, char **state);
 	netpbm fixes by Alan Cox. */

 int overflow2(int a, int b);
+int overflowMul3(int a, int b, int c);

 #ifdef ZTS
 #define gdMutexDeclare(x) MUTEX_T x
diff --git a/ext/gd/tests/gh19739.phpt b/ext/gd/tests/gh19739.phpt
new file mode 100644
index 00000000000..7dce387b780
--- /dev/null
+++ b/ext/gd/tests/gh19739.phpt
@@ -0,0 +1,18 @@
+--TEST--
+GH-19739 (integer overflow in imageellipse / imagefilledellipse)
+--EXTENSIONS--
+gd
+--FILE--
+<?php
+$im = imagecreatetruecolor(400, 300);
+$color = imagecolorallocate($im, 150, 255, 0);
+
+var_dump(imageellipse($im, 64, 150, 2147483647, 2147483647, $color));
+var_dump(imagefilledellipse($im, 64, 150, 2147483647, 2147483647, $color));
+
+echo "done" . PHP_EOL;
+?>
+--EXPECT--
+bool(true)
+bool(true)
+done