-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix detection of image formats in system gd #12029
Conversation
Very good find. Thanks, @orlitzky Yes, the libgd seems to need some patches from the php-src or some further code adjustments at least. Because with the bundled libgd all of these seem to work ok. I can't think of the better way at the moment so let's go with this. Seems good. Also, let's add this to PHP-8.1 so we have current maintained branches all fixed. I'll check for more soon... |
Thanks! Cross-compilation makes it past I was wondering why upstream libgd might have left those stub functions enabled. It looks intentional, so... maybe it's to avoid changing the API/ABI based on build-time choices? This PR reveals some more test failures (in addition the remaining few in #11252) when the system gd lacks PNG support.They're easy to fix though and I'll work on it when this is done. |
There is this constant --- a/ext/gd/config.m4
+++ b/ext/gd/config.m4
@@ -140,9 +140,9 @@ AC_DEFUN([PHP_GD_JISX0208],[
dnl Build and run a program to determine if GD has support for the given
-dnl format. The sole argument is the proper-noun-capitalized name of the
+dnl format. The first argument is the proper-noun-capitalized name of the
dnl format -- basically the word Foo in gdImageCreateFromFoo -- such as
-dnl Png. If support for format Foo exists, HAVE_GD_FOO will be defined
+dnl Png. If support for format Foo exists, 2nd argument will be defined
dnl to 1. The reason for this charade is that gd defines "junk" versions
dnl of each gdImageCreateFromFoo function even when it does not support
dnl the Foo format. Those junk functions display a warning but eventually
@@ -171,7 +171,7 @@ int main(int argc, char** argv) {
return 0;
} ]])],[
AC_MSG_RESULT([yes])
- AC_DEFINE(HAVE_GD_[]m4_toupper($1), 1, [ ])
+ AC_DEFINE([$2], 1, [ ])
],[
AC_MSG_RESULT([no])
],[
@@ -182,13 +182,13 @@ int main(int argc, char** argv) {
])
AC_DEFUN([PHP_GD_CHECK_VERSION],[
- PHP_GD_CHECK_FORMAT([Png])
- PHP_GD_CHECK_FORMAT([Avif])
- PHP_GD_CHECK_FORMAT([Webp])
- PHP_GD_CHECK_FORMAT([Jpeg])
- PHP_GD_CHECK_FORMAT([Xpm])
- PHP_GD_CHECK_FORMAT([Bmp])
- PHP_GD_CHECK_FORMAT([Tga])
+ PHP_GD_CHECK_FORMAT([Png],[HAVE_GD_PNG])
+ PHP_GD_CHECK_FORMAT([Avif],[HAVE_GD_AVIF])
+ PHP_GD_CHECK_FORMAT([Webp],[HAVE_GD_WEBP])
+ PHP_GD_CHECK_FORMAT([Jpeg],[HAVE_GD_JPG])
+ PHP_GD_CHECK_FORMAT([Xpm],[HAVE_GD_XPM])
+ PHP_GD_CHECK_FORMAT([Bmp],[HAVE_GD_BMP])
+ PHP_GD_CHECK_FORMAT([Tga],[HAVE_GD_TGA])
PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_FREETYPE, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdVersionString, [AC_DEFINE(HAVE_GD_LIBVERSION, 1, [ ])], [], [ $GD_SHARED_LIBADD ])
PHP_CHECK_LIBRARY(gd, gdImageGetInterpolationMethod, [AC_DEFINE(HAVE_GD_GET_INTERPOLATION, 1, [ ])], [], [ $GD_SHARED_LIBADD ]) |
Currently we look for gdImageStringFT() to determine whether or not gd has freetype support... but that function always exists. This leads PHP to believe that gd has freetype support when it does not, and can lead to build failures (GH 12019). The gdFontCacheShutdown() function, on the other hand, is only present when gd was built with freetype support. Let's use that instead.
We currently check for, say, AVIF support by attempting to link a program that calls libgd's gdImageCreateFromAvif() function. But perversely, that function always exists in libgd; moreover when AVIF support is missing it emits a warning and returns normally. Thus our straightforward link test becomes not so straightforward. This commit adds a new macro PHP_GD_CHECK_FORMAT that compiles, links, and runs a test program instead. The test program overrides that "emit a warning" handler so that the program actually fails if the format we're looking for is not supported. This fixes detection of AVIF and the other formats we check for in an external libgd. Closes phpGH-12019
I don't actually know how to remove BMP support from libgd, but PHP has a ./configure test for it, so we should probably treat it as optional.
The AC_RUN_IFELSE inside PHP_GD_CHECK_FORMAT was missing its third argument, namely what to do when the user is cross-compiling. Its absence is not immediately fatal, but it does cause ./configure to bail out if the user attempts to cross-compile. We add a pessimistic default (format not supported) for that case to allow ./configure to proceed.
The new gd format detection macro accidentally renames HAVE_GD_JPG to HAVE_GD_JPEG because gd uses "Jpeg" in its function names. But this would break consumers for no reason. Instead we require the caller to pass in the name of the constant explicitly, and when checking for Jpeg support, we pass in HAVE_GD_JPG. Thanks to Peter Kokot for the suggestion.
We know what these constants indicate, so it doesn't hurt to explain them via the third argument to AC_DEFINE.
5bf1895
to
93f7967
Compare
Hi, sorry for the delay, I never got the email notification for this comment and it took me a few months to independently wonder what ever happened to this PR. I've implemented your suggestion. Renaming the constant was unintentional. |
Looks good to me. I'll recheck it in the following days and move forward with merging this soon... |
Hello, looks ok now, yes. I'll only add this change into the PR if that's fine with you and merge this in the following day(s) to master branch: diff --git a/ext/gd/config.m4 b/ext/gd/config.m4
index c427a29f31..c453c0f38d 100644
--- a/ext/gd/config.m4
+++ b/ext/gd/config.m4
@@ -153,7 +153,7 @@ AC_DEFUN([PHP_GD_CHECK_FORMAT],[
LIBS="${LIBS} ${GD_SHARED_LIBADD}"
AC_MSG_CHECKING([for working gdImageCreateFrom$1 in libgd])
AC_LANG_PUSH([C])
- AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ AC_RUN_IFELSE([AC_LANG_SOURCE([
#include <stdio.h>
#include <unistd.h>
#include <gd.h>
@@ -166,11 +166,13 @@ void exit1(int priority, const char *format, va_list args) {
/* Override the default gd_error_method with one that
actually causes the program to return an error. */
int main(int argc, char** argv) {
- FILE* f = NULL;
+ m4_if([$1],[Xpm],
+ [char* f = "test.xpm"],
+ [FILE* f = NULL]);
gdSetErrorMethod(exit1);
gdImagePtr p = gdImageCreateFrom$1(f);
return 0;
-} ]])],[
+}])],[
AC_MSG_RESULT([yes])
AC_DEFINE($2, 1, [Does gdImageCreateFrom$1 work?])
],[ Because the
and somehow test waits for the user input with certain build configurations. Other functions are OK. |
Yeah good catch, I didn't notice the different argument type. Thanks again. |
No problem, thanks for your help with this. |
Will this be backported to maintained branches or is it PHP 8.4 only? |
I guess we could add it to PHP-8.2. I was a bit worried for the existing builds out there if it might cause issues. 🤔 |
We currently get false positives when checking for, say, AVIF support in the system libgd: #12019
I replaced the existing link tests with run tests of a little gd program that seems to do the trick.