Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 120908

Summary: libphp5.so exports symbols which conflict with modules loaded by mod_perl
Product: Gentoo Linux Reporter: Nicholas Vinen <hb>
Component: [OLD] ServerAssignee: PHP Bugs <php-bugs>
Status: RESOLVED FIXED    
Severity: normal    
Priority: High    
Version: 2005.1   
Hardware: x86   
OS: Linux   
URL: http://bugs.php.net/36208
Whiteboard: watch-php-bugzilla
Package list:
Runtime testing required: ---
Attachments: php-5.0.5-gd-compat-backport.patch
Patch to fix include errors.
Fixed/merged patch
php-5.1.2-gd-compat.patch

Description Nicholas Vinen 2006-01-30 00:10:23 UTC
This is an extract of the symbols in /usr/lib/apache/modules/libphp5.so which belongs to dev-lang/php-5.0.5-r5:

nexus GD-2.30 # nm -D /usr/lib/apache/modules/libphp5.so | grep gdImagePng
000faaa4 T gdImagePng
000fab34 T gdImagePngCtx
000fa3b0 T gdImagePngCtxEx
000faa80 T gdImagePngEx
000faac8 T gdImagePngPtr
000faafc T gdImagePngPtrEx
000f9b70 T gdImagePngToSink

This is the originating library:
nexus GD-2.30 # nm -D /usr/lib/libgd.so | grep gdImagePng
00010200 T gdImagePng
000102b8 T gdImagePngCtx
000102d8 T gdImagePngCtxEx
000101d0 T gdImagePngEx
00010230 T gdImagePngPtr
00010274 T gdImagePngPtrEx
00010b48 T gdImagePngToSink

The problem is this:

dev-perl/GD-2.30 (/usr/lib/perl5/vendor_perl/5.8.7/i686-linux/auto/GD/GD.so)

nexus GD-2.30 # nm -D /usr/lib/perl5/vendor_perl/5.8.7/i686-linux/auto/GD/GD.so | grep gdImagePng
         U gdImagePngPtr
         U gdImagePngPtrEx

When I write a mod_perl script which loads the GD module and calls the GD::Image->png() function which calls gdImagePngPtr, it ends up in libphp5.so instead of libgd.so, which is not compiled the same, and often corrupts memory resulting in an apache child crash.

If I do not load libphp5.so into apache, the script works as normal.

I suspect deep down this is a problem with glibc/the dynamic linker. I'm not sure how to go about fixing it. But it's an annoying problem, as my friend wants to write PHP scripts and I want to write perl scripts which use GD.
Comment 1 Jakub Moc (RETIRED) gentoo-dev 2006-01-30 00:32:01 UTC
Not really sure what kind of fix do you expect from us, both things link against media-libs/gd, so they export the same symbols...
Comment 2 Nicholas Vinen 2006-01-30 01:01:36 UTC
I worked around this problem by doing the following:

USE="gd-external -gd -tiff" emerge =dev-lang/php-5.0.5-r5

This builds php-5.0.5-r5 without linking to libgd statically. Because it's dynamically linked, it imports the symbols rather than exporting them, and thus does not confuse the dynamic linker.

I still think this is a problem, though. Firstly, this took me hours to track down and fix, and if it's going to be a serious problem the "gd" option of php should proably be removed and replaced with gd-external only. (I'm not sure what the advantage of statically linking it is - speed?) Or else a big warning should be put there. Secondly, for some reason I have to disable TIFF support in PHP since it thinks it needs gd to build TIFF support, even though gd-external is being used. Ideally this should be fixed so you can link the module either way and it should work. I think this might need a change/fix to glibc/the dynamic linker to achieve.
Comment 3 Nicholas Vinen 2006-01-30 01:05:24 UTC
Well, if you are not willing to fix the base problem, perhaps you know who to notify about this?

It was a giant pain and time-waster for me to have to track this down, and I know how to debug C programs. I can't imagine how many problems this would cause a newbie. They'd be tearing their hair out. So I would suggest:

* Find a way to work-around this so it can't happen. For example, somehow make the "gd" option from libphp5 hard to enable. For example, if it's enabled, print a big warning saying "ABANDON HOPE ALL YE WHO ENTER HERE - If you really, really want to do this (explain why it's a bad idea) use the gd-force-php5 flag" and then exit. This way people can't accidentally fall into this trap.
* Let the glibc people know this is broken. I can do this if you want. In my opinion this is a serious failure of the dynamic linker system as a robust tool.
Comment 4 Nicholas Vinen 2006-01-30 03:14:28 UTC
OK, I think I now understand exactly what is going on.

The problem is that PHP contains its own implementation of GD, but they didn't change the symbol names so they won't collide:

hb@nexus /var/tmp/portage/php-5.1.1/work $ find . -name *gd*
./php-5.1.1/ext/gd/libgd
./php-5.1.1/ext/gd/libgd/gd.c
./php-5.1.1/ext/gd/libgd/gd.h
./php-5.1.1/ext/gd/libgd/gdtables.c
...

These are obviously not properly compatible with libgd. Yet the symbol names are the same. So if two .so files are loaded into the same application space, one uses libgd and the other uses libphp5, gd will break.

The best solution would be, in my opinion, for PHP to use only libgd under Gentoo. Gentoo portage can automatically pull the library in and keep it up to date. This removes the advantage of packaging them together, IMO.

Is there an advantage to using the built-in one over libgd?

If not, my recommendations are:

* Gentoo fix: libphp5 ALWAYS uses libgd, never built-in gd.
* PHP fix: Notify PHP team of the problem. Recommend they prefix the symbols in the built-in version to avoid this conflict in future. Or else use library versioning so that the linker will not confuse the symbols.
* GLIBC fix: Recommend to GNU that future dynamic linker spits out an error in the case where a process loads the same symbol from multiple different locations and the data at the symbol does not match. Otherwise this kind of problem has the potential for happening.
Comment 5 Luca Longinotti (RETIRED) gentoo-dev 2006-01-30 03:33:51 UTC
(In reply to comment #4) 
> * Gentoo fix: libphp5 ALWAYS uses libgd, never built-in gd.

No. The GD that PHP bundles is specifically enhanced to work with PHP (new features, changed stuff, performance), so it will remain as an option (and it should be used by default).

> * PHP fix: Notify PHP team of the problem. Recommend they prefix the symbols
> in the built-in version to avoid this conflict in future. Or else use library
> versioning so that the linker will not confuse the symbols.

This is imo the only correct fix, please open a bug at http://bugs.php.net/ about it and link it back here, so we can implement the patch in Gentoo's PHP once upstream has done it (IF they will). Try to get that fix in both PHP4 and PHP5, as I assume PHP4 has it too, since it uses the bundled library too.

> * GLIBC fix: Recommend to GNU that future dynamic linker spits out an error in
> the case where a process loads the same symbol from multiple different
> locations and the data at the symbol does not match. Otherwise this kind of
> problem has the potential for happening.

Don't know about this, anyway still an upstream question, ask glibc people.$
Best regards, CHTEKK.
Comment 6 Luca Longinotti (RETIRED) gentoo-dev 2006-01-30 03:35:38 UTC
Ups sorry, reopen as it's not assigned to us and so that glibc maintainer can comment wrt the possible glibc change/fix...
Best regards, CHTEKK.
Comment 7 Nicholas Vinen 2006-01-30 03:48:56 UTC
I agree, if this is fixed in PHP then the built-in GD can continue to be used as default. Here is the bug report I have submitted:

http://bugs.php.net/36208

I do think it's a problem that the dynamic loader will happily associate the symbols wrong. The PHP people should have renamed or changed the version of the symbols, but ideally this bug should be caught and reported, rather than causing random crashes. Perhaps the dynamic linker can check if it expects to be pulling in dynamic symbols from libgd.so and it finds them in a different .so, and print a warning message. I realize there are situations where you might actually want this, but can they be somehow distinguished so that these incorrect occasions are caught?

Perhaps it's too difficult but I think it would be beneficial overall.
Comment 8 Jakub Moc (RETIRED) gentoo-dev 2006-01-30 03:57:52 UTC
Re-assign (it's been assigned to vapier as media-libs/gd maintainer, but there's nothing wrong with that one it appears.)

(In reply to comment #7)
> Here is the bug report I have submitted:
> 
> http://bugs.php.net/36208

Thanks.

> I do think it's a problem that the dynamic loader will happily associate the
> symbols wrong. 

CCing toolchain if they wish to comment on this.
Comment 9 SpanKY gentoo-dev 2006-01-30 06:34:19 UTC
you dont need to rename them, just mark them with hidden visibility
Comment 10 Jakub Moc (RETIRED) gentoo-dev 2006-01-30 11:23:27 UTC
Marking this upstream, will be fixed when upstream fixes the issue.
Comment 11 Nicholas Vinen 2006-01-31 20:35:38 UTC
The PHP people are refusing to fix this (see http://bugs.php.net/36208). What do I do now? If I come up with a patch which stops these symbols being exported from PHP can we put it into portage? Alternatively, perhaps we can make the PHP and PERL ebuilds detect this problem and warn the user about it. However, I prefer a fix which stops this from happening without affecting the user's options, which the patch should provide.
Comment 12 Jakub Moc (RETIRED) gentoo-dev 2006-02-01 02:05:09 UTC
Uhm, while we could fix the issue for Gentoo (when someone produces the patch), this is really of no use for other PHP users, it really needs to go upstream. We won't be forcing gd-external on people, that's not a solution and mod_perl is just one of the the examples where this may screw things up...

Anyway, looks fixed upstream in >=5.1.1 at least... This should be backported upstream for 4.4.x, I highly doubt they will fix 5.0.x, as there won't be 5.0.6 release ever, AFAIK.
Comment 13 Nicholas Vinen 2006-02-01 02:14:02 UTC
Ah, it may be fixed in 5.1.1 but that is not marked as stable on x86, hence when I install dev-lang/php I get 5.0.5-r5 which presumably still has this bug. Perhaps it would therefore be worth putting a patch in Gentoo until 5.1.1 is marked as stable?

I will try installing dev-lang/php-5.1.1 and see if the problem is gone.
Comment 14 Luca Longinotti (RETIRED) gentoo-dev 2006-02-01 02:27:21 UTC
Strange though that 5.1.1 fixes it??? As there were no changes to main/php_compat.h and to the gd libs/ext that would "fix" this, at least I could fine none in CVS. But indeed in 5.1.1:
08153cf7 T php_gd_gdImagePng
08153be3 T php_gd_gdImagePngCtx
08153223 T php_gd_gdImagePngCtxEx
08153d45 T php_gd_gdImagePngEx
08153c85 T php_gd_gdImagePngPtr
08153c13 T php_gd_gdImagePngPtrEx
08152328 T php_gd_gdImagePngToSink
So they get correctly prefixed... But in PHP 4.4.1 they aren't, still need to test 4.4.2, but there are others that aren't prefixed yet... I'll see to fix those.
Best regards, CHTEKK.
Comment 15 Luca Longinotti (RETIRED) gentoo-dev 2006-02-01 02:32:02 UTC
Update: I checked the sources a little more, it seems that PHP 4.X (all) and PHP 5.0.X (all) do not have any of those GD prefixes, they were only introduced with PHP 5.1.1 (see line 127+ of main/php_compat.h of PHP 5.1.X).
So the fix will have to be backported to older PHP versions, I'll test this this evening, as I'm not sure if it will break other stuff, but it shouldn't.
Best regards, CHTEKK.
Comment 16 Jakub Moc (RETIRED) gentoo-dev 2006-02-01 02:32:20 UTC
Created attachment 78631 [details, diff]
php-5.0.5-gd-compat-backport.patch

Please, test this patch and report back.

Download the attached patch to dev-lang/php/files and modify the ebuild:

--- php-5.0.5-r5.ebuild.orig    2006-01-26 01:06:18.000000000 +0100
+++ php-5.0.5-r5.ebuild 2006-02-01 11:28:52.000000000 +0100
@@ -87,6 +87,7 @@
        # patch to fix safe_mode bypass in GD extension, bug #109669
        if use gd || use gd-external ; then
                epatch "${WORKDIR}/${PV}/php${PV}-gd-safe_mode.patch"
+               epatch "${FILESDIR}/php-5.0.5-gd-compat-backport.patch"
        fi

        # patch open_basedir directory bypass, bug #102943
Comment 17 Jakub Moc (RETIRED) gentoo-dev 2006-02-01 02:34:21 UTC
Let us know how it goes...
Comment 18 Nicholas Vinen 2006-02-01 02:47:32 UTC
I think you're on to the right track but I get this when building after the patch:

ext/gd/gd.o: In function `zif_imagecreatefromstring':
gd.c:(.text+0x29a7): undefined reference to `php_gd_gdImageCreateFromWBMPCtx'
ext/gd/gd.o: In function `zif_imagecreatefromwbmp':
gd.c:(.text+0x8271): undefined reference to `php_gd_gdImageCreateFromWBMPCtx'
gd.c:(.text+0x8276): undefined reference to `php_gd_gdImageCreateFromWBMP'
ext/gd/gd.o: In function `zif_imagecreatefromgd':
gd.c:(.text+0x829d): undefined reference to `php_gd_gdImageCreateFromGdCtx'
gd.c:(.text+0x82a2): undefined reference to `php_gd_gdImageCreateFromGd'
ext/gd/gd.o: In function `zif_imagegif':
gd.c:(.text+0x8349): undefined reference to `php_gd_gdImageGifCtx'
ext/gd/gd.o: In function `zif_imagewbmp':
gd.c:(.text+0x83c1): undefined reference to `php_gd_gdImageWBMPCtx'
ext/gd/gd.o: In function `zif_imagegd':
gd.c:(.text+0x83e9): undefined reference to `php_gd_gdImageGd'
ext/gd/gd.o: In function `_php_image_output':
gd.c:(.text+0x9778): undefined reference to `php_gd_gdImageWBMP'
gd.c:(.text+0x98a5): undefined reference to `php_gd_gdImageWBMP'
ext/gd/gd.o: In function `_php_image_type':
gd.c:(.text+0x9a22): undefined reference to `php_gd_gdGetC'
gd.c:(.text+0x9a33): undefined reference to `php_gd_gdGetC'
ext/gd/gd.o: In function `_php_image_convert':
gd.c:(.text+0xa088): undefined reference to `php_gd_gdImageWBMP'
ext/gd/gd.o: In function `php_find_gd_font':
gd.c:(.text+0xa967): undefined reference to `php_gd_gdFontTiny'
gd.c:(.text+0xa96f): undefined reference to `php_gd_gdFontSmall'
gd.c:(.text+0xa977): undefined reference to `php_gd_gdFontMediumBold'
gd.c:(.text+0xa97f): undefined reference to `php_gd_gdFontLarge'
gd.c:(.text+0xa987): undefined reference to `php_gd_gdFontGiant'
gd.c:(.text+0xa9ad): undefined reference to `php_gd_gdFontGiant'
gd.c:(.text+0xa9b6): undefined reference to `php_gd_gdFontTiny'
ext/gd/gd.o: In function `_php_image_bw_convert':
gd.c:(.text+0x7f9c): undefined reference to `php_gd_gdImageWBMPCtx'
ext/gd/libgd/gd.o: In function `php_gd_gdImageFilledArc':
gd.c:(.text+0x21b1): undefined reference to `php_gd_gdCosT'
gd.c:(.text+0x21c9): undefined reference to `php_gd_gdSinT'
ext/gd/libgd/gd_gd.o: In function `gdImageCreateFromGdCtx':
gd_gd.c:(.text+0x1e7): undefined reference to `gdImageDestroy'
ext/gd/libgd/gd_gd.o: In function `gdImageCreateFromGd':
gd_gd.c:(.text+0x1ff): undefined reference to `gdNewFileCtx'
ext/gd/libgd/gd_gd.o: In function `gdImageCreateFromGdPtr':
gd_gd.c:(.text+0x229): undefined reference to `gdNewDynamicCtxEx'
ext/gd/libgd/gd_gd.o: In function `gdImageGd':
gd_gd.c:(.text+0x2e7): undefined reference to `gdNewFileCtx'
ext/gd/libgd/gd_gd.o: In function `gdImageGdPtr':
gd_gd.c:(.text+0x35c): undefined reference to `gdNewDynamicCtx'
gd_gd.c:(.text+0x3bc): undefined reference to `gdDPExtractData'
ext/gd/libgd/gd_gd.o: In function `_gdCreateFromFile':
gd_gd.c:(.text+0x438): undefined reference to `gdImageCreateTrueColor'
gd_gd.c:(.text+0x443): undefined reference to `gdImageCreate'
gd_gd.c:(.text+0x460): undefined reference to `gdImageDestroy'
ext/gd/libgd/gd_gd2.o: In function `php_gd_gdImageCreateFromGd2Ctx':
gd_gd2.c:(.text+0x174): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0x183): undefined reference to `php_gd_gdSeek'
gd_gd2.c:(.text+0x193): undefined reference to `php_gd_gdGetBuf'
gd_gd2.c:(.text+0x24e): undefined reference to `php_gd_gdGetInt'
gd_gd2.c:(.text+0x27c): undefined reference to `php_gd_gdGetByte'
ext/gd/libgd/gd_gd2.o: In function `php_gd_gdImageCreateFromGd2PartCtx':
gd_gd2.c:(.text+0x4ca): undefined reference to `php_gd__gdGetColors'
gd_gd2.c:(.text+0x5da): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0x69e): undefined reference to `php_gd_gdSeek'
gd_gd2.c:(.text+0x6ea): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0x6f9): undefined reference to `php_gd_gdSeek'
gd_gd2.c:(.text+0x709): undefined reference to `php_gd_gdGetBuf'
gd_gd2.c:(.text+0x785): undefined reference to `php_gd_gdGetInt'
gd_gd2.c:(.text+0x794): undefined reference to `php_gd_gdGetC'
ext/gd/libgd/gd_gd2.o: In function `_gd2GetHeader':
gd_gd2.c:(.text+0xa73): undefined reference to `php_gd_gdGetC'
gd_gd2.c:(.text+0xaad): undefined reference to `php_gd_gdGetWord'
gd_gd2.c:(.text+0xad0): undefined reference to `php_gd_gdGetWord'
gd_gd2.c:(.text+0xae4): undefined reference to `php_gd_gdGetWord'
gd_gd2.c:(.text+0xaf8): undefined reference to `php_gd_gdGetWord'
gd_gd2.c:(.text+0xb1c): undefined reference to `php_gd_gdGetWord'
ext/gd/libgd/gd_gd2.o:gd_gd2.c:(.text+0xb3b): more undefined references to `php_gd_gdGetWord' follow
ext/gd/libgd/gd_gd2.o: In function `_gd2GetHeader':
gd_gd2.c:(.text+0xb92): undefined reference to `php_gd_gdGetInt'
gd_gd2.c:(.text+0xba1): undefined reference to `php_gd_gdGetInt'
ext/gd/libgd/gd_gd2.o: In function `_gd2CreateFromFile':
gd_gd2.c:(.text+0xc39): undefined reference to `php_gd__gdGetColors'
ext/gd/libgd/gd_gd2.o: In function `_gdImageGd2':
gd_gd2.c:(.text+0xd36): undefined reference to `php_gd_gdPutC'
gd_gd2.c:(.text+0xd48): undefined reference to `php_gd_gdPutWord'
gd_gd2.c:(.text+0xd5a): undefined reference to `php_gd_gdPutWord'
gd_gd2.c:(.text+0xd6c): undefined reference to `php_gd_gdPutWord'
gd_gd2.c:(.text+0xd7b): undefined reference to `php_gd_gdPutWord'
gd_gd2.c:(.text+0xd8a): undefined reference to `php_gd_gdPutWord'
ext/gd/libgd/gd_gd2.o:gd_gd2.c:(.text+0xd99): more undefined references to `php_gd_gdPutWord' follow
ext/gd/libgd/gd_gd2.o: In function `_gdImageGd2':
gd_gd2.c:(.text+0xe2b): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0xe4e): undefined reference to `php_gd_gdSeek'
gd_gd2.c:(.text+0xe75): undefined reference to `php_gd__gdPutColors'
gd_gd2.c:(.text+0xf9a): undefined reference to `php_gd_gdPutInt'
gd_gd2.c:(.text+0xfb3): undefined reference to `php_gd_gdPutC'
gd_gd2.c:(.text+0x100b): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0x1031): undefined reference to `php_gd_gdPutBuf'
gd_gd2.c:(.text+0x108b): undefined reference to `php_gd_gdTell'
gd_gd2.c:(.text+0x109a): undefined reference to `php_gd_gdSeek'
gd_gd2.c:(.text+0x10b3): undefined reference to `php_gd_gdPutInt'
gd_gd2.c:(.text+0x10c5): undefined reference to `php_gd_gdPutInt'
gd_gd2.c:(.text+0x10d8): undefined reference to `php_gd_gdSeek'
ext/gd/libgd/gd_ss.o: In function `gdImagePngToSink':
gd_ss.c:(.text+0x8): undefined reference to `gdNewSSCtx'
gd_ss.c:(.text+0x14): undefined reference to `gdImagePngCtx'
ext/gd/libgd/gd_ss.o: In function `gdImageCreateFromPngSource':
gd_ss.c:(.text+0x2d): undefined reference to `gdNewSSCtx'
gd_ss.c:(.text+0x35): undefined reference to `gdImageCreateFromPngCtx'
ext/gd/libgd/gd_png.o: In function `php_gd_gdImageCreateFromPngCtx':
...

I think perhaps some files are not including php_compat.h, probably just ext/gd/gd.c. Since, notice that some files have undefined references to php_gd_* (meaning they include php_compat.h, but not the file that defines those symbols) and some have undefined references to gd* (meaning they probably don't include php_compat.h).
Comment 19 Luca Longinotti (RETIRED) gentoo-dev 2006-02-01 03:07:39 UTC
Created attachment 78633 [details, diff]
Patch to fix include errors.

This should fix those, please test, thanks!
Best regards, CHTEKK.
Comment 20 Nicholas Vinen 2006-02-01 03:31:16 UTC
Created attachment 78638 [details, diff]
Fixed/merged patch
Comment 21 Nicholas Vinen 2006-02-01 03:34:41 UTC
OK, I attached the patch I merged from the two you provided which seems to work. I also added six more renamed function calls for gd, which were still being exported to the .so file. Everything seems fine now. The only remaining issue may be to get those six patched in the next release of PHP 5.1.x. I'll try to do that tomorrow. They do not seem to cause any problems but it's hard to be sure, as it may only be because I'm not calling them in my test case.
Comment 22 Jakub Moc (RETIRED) gentoo-dev 2006-02-01 03:40:11 UTC
(In reply to comment #21)
Uhm, I'd say don't bother with that, it's upstream job really - just forward the patch upstream so that they can fix their stuff, instead of requesting a backtrace, huh.

Thanks for testing and help.
Comment 23 Jakub Moc (RETIRED) gentoo-dev 2006-02-01 04:05:54 UTC
Created attachment 78639 [details, diff]
php-5.1.2-gd-compat.patch

Adding those 6 additional compatibility symbols to main/php_compat.h in php-5.1.2
Comment 24 Luca Longinotti (RETIRED) gentoo-dev 2006-03-12 05:41:42 UTC
This was now fixed upstream in 5.1.3RC1, but will afaik not be fixed in the PHP 4.X series.
I backported the various patches to all our PHP relases now, emerge --sync in a couple of hours and you should get them, PHP 4.4.2 and PHP 5.1.2 were added to the Portage tree including those fixes (as I also added them to our PHP 4.X releases).
Best regards, CHTEKK.