php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48619 imap_search() ALL causing segfault
Submitted: 2009-06-20 16:44 UTC Modified: 2009-06-22 21:44 UTC
From: andy at webtatic dot com Assigned: pajoye
Status: Closed Package: IMAP related
PHP Version: 5.2.10 OS: CentOS 5.3 i386
Private report: No CVE-ID:
 [2009-06-20 16:44 UTC] andy at webtatic dot com
Description:
------------
imap_search($connection, 'ALL') seems to be causing a segmentation fault.

The backtrace (from what I guess), seems to suggest the command is recursively calling itself to free the searchset, the same thing being called endlessly.

The php build was based on the CentOS testing php-5.2.6 rpm modified to compile php-5.2.10. php-5.2.9 did not have this issue.

build --enable-force-cgi-redirect \
      --enable-pcntl \
      --with-imap=shared --with-imap-ssl \
      --enable-mbstring=shared --enable-mbstr-enc-trans \
      --enable-mbregex \
      --with-ncurses=shared \
      --with-gd=shared \
      --enable-bcmath=shared \
      --enable-dba=shared --with-db4=%{_prefix} \
      --with-xmlrpc=shared \
      --with-ldap=shared --with-ldap-sasl \
      --with-mysql=shared,%{_prefix} \
      --with-mysqli=shared,%{_bindir}/mysql_config \
      --enable-dom=shared \
      --with-dom-xslt=%{_prefix} --with-dom-exslt=%{_prefix} \
      --with-pgsql=shared \
      --with-snmp=shared,%{_prefix} \
      --enable-soap=shared \
      --with-xsl=shared,%{_prefix} \
      --enable-xmlreader=shared --enable-xmlwriter=shared \
      --enable-fastcgi \
      --enable-pdo=shared \
      --with-pdo-odbc=shared,unixODBC,%{_prefix} \
      --with-pdo-mysql=shared,%{_prefix} \
      --with-pdo-pgsql=shared,%{_prefix} \
      --with-pdo-sqlite=shared,%{_prefix} \
      --enable-json=shared \
      --enable-zip=shared \
      --with-readline \
      --enable-dbase=shared \
      --enable-debug

Actual result:
--------------
#0  0x020393ff in mail_free_searchset () from /usr/lib/libc-client.so.1
#1  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#2  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#3  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#4  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#5  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#6  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#7  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#8  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#9  0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
#10 0x0203941b in mail_free_searchset () from /usr/lib/libc-client.so.1
...



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-06-20 16:56 UTC] pajoye@php.net
Please compile in debug mode (--enable-debug) and provide again the backtrace.

Which c-client version do you use?
 [2009-06-20 17:41 UTC] andy at webtatic dot com
The c client I'm using is the one part of CentOS 5.3, 2004g-2.2.1

I added the --enable-debug to the configure earlier, and got a php build that had a version like:
PHP 5.2.10 (cli) (built: Jun 20 2009 18:09:52) (DEBUG)

I'm not sure why its not adding debug information.

Sorry, the proper ./configure is more like:

configure \
        --cache-file=../config.cache \
        --with-libdir=%{_lib} \
        --with-config-file-path=%{_sysconfdir} \
        --with-config-file-scan-dir=%{_sysconfdir}/php.d \
        --with-pic \
        --disable-rpath \
        --without-pear \
        --with-bz2 \
        --with-curl \
        --with-exec-dir=%{_bindir} \
        --with-freetype-dir=%{_prefix} \
        --with-png-dir=%{_prefix} \
        --enable-gd-native-ttf \
        --without-gdbm \
        --with-gettext \
        --with-gmp \
        --with-iconv \
        --with-jpeg-dir=%{_prefix} \
        --with-openssl \
        --with-png \
        --with-pspell \
        --with-expat-dir=%{_prefix} \
        --with-pcre-regex=%{_prefix} \
        --with-zlib \
        --with-layout=GNU \
        --enable-exif \
        --enable-ftp \
        --enable-magic-quotes \
        --enable-sockets \
        --enable-sysvsem --enable-sysvshm --enable-sysvmsg \
        --enable-track-vars \
        --enable-trans-sid \
        --enable-yp \
        --enable-wddx \
        --with-kerberos \
        --enable-ucd-snmp-hack \
        --with-unixODBC=shared,%{_prefix} \
        --enable-memory-limit \
        --enable-shmop \
        --enable-calendar \
        --enable-dbx \
        --enable-dio \
        --without-mime-magic \
        --without-sqlite \
        --with-libxml-dir=%{_prefix} \
        --with-xml \
        --with-system-tzdata \
        --enable-debug \
--enable-force-cgi-redirect \
      --enable-pcntl \
      --with-imap=shared --with-imap-ssl \
      --enable-mbstring=shared --enable-mbstr-enc-trans \
      --enable-mbregex \
      --with-ncurses=shared \
      --with-gd=shared \
      --enable-bcmath=shared \
      --enable-dba=shared --with-db4=%{_prefix} \
      --with-xmlrpc=shared \
      --with-ldap=shared --with-ldap-sasl \
      --with-mysql=shared,%{_prefix} \
      --with-mysqli=shared,%{_bindir}/mysql_config \
      --enable-dom=shared \
      --with-dom-xslt=%{_prefix} --with-dom-exslt=%{_prefix} \
      --with-pgsql=shared \
      --with-snmp=shared,%{_prefix} \
      --enable-soap=shared \
      --with-xsl=shared,%{_prefix} \
      --enable-xmlreader=shared --enable-xmlwriter=shared \
      --enable-fastcgi \
      --enable-pdo=shared \
      --with-pdo-odbc=shared,unixODBC,%{_prefix} \
      --with-pdo-mysql=shared,%{_prefix} \
      --with-pdo-pgsql=shared,%{_prefix} \
      --with-pdo-sqlite=shared,%{_prefix} \
      --enable-json=shared \
      --enable-zip=shared \
      --with-readline \
      --enable-dbase=shared
 [2009-06-20 18:01 UTC] andy at webtatic dot com
I've done a simple build of php using the php-5.2.10.tar.gz from php.net, and it has the same issue. It still segfaults, and doesn't contain additional debug information:

./configure --enable-debug --with-imap --with-imap-ssl --with-kerberos --with-openssl --with-mysql

gdb ./sapi/cli/php
run myscript.php

Program received signal SIGSEGV, Segmentation fault.
0x0012f3ff in mail_free_searchset () from /usr/lib/libc-client.so.1
(gdb) bt
#0  0x0012f3ff in mail_free_searchset () from /usr/lib/libc-client.so.1
#1  0x0012f41b in mail_free_searchset () from /usr/lib/libc-client.so.1
#2  0x0012f41b in mail_free_searchset () from /usr/lib/libc-client.so.1
#3  0x0012f41b in mail_free_searchset () from /usr/lib/libc-client.so.1
#4  0x0012f41b in mail_free_searchset () from /usr/lib/libc-client.so.1
 [2009-06-20 20:10 UTC] pajoye@php.net
Hm, this version is outdated. Can you try using a decent version? 2007x (where x is a letter). You can get it here:

http://www.washington.edu/imap/
 [2009-06-20 20:30 UTC] andy at webtatic dot com
Ok, I did some investigating and found out it is caused by the fix #47940.

If no search flags are set, you set flags to SE_FREE, which mail_search_full then frees the pgm internally, but then you then free again, causing the segfault. This will be an issue on any OS.

The correct way to do it would probably be to always add the SE_FREE flag and let it do it itself, and not free in imap_search.
 [2009-06-20 20:34 UTC] andy at webtatic dot com
Also looking at c-client's latest, the same internal free happens, so will cause the same problem.
 [2009-06-20 20:39 UTC] pajoye@php.net
Ah nice catch for this edge case. I will fix it soonish. Thanks :)
 [2009-06-20 20:54 UTC] andy at webtatic dot com
I've made a patch for it, as I'd like to have it patched in my rpms of 5.2.10.

I can't see anywhere to upload files, so I'll post it here, only short:

--- php-5.2.10/ext/imap/php_imap.c.pgmfree	2009-06-20 21:44:54.000000000 +0100
+++ php-5.2.10/ext/imap/php_imap.c	2009-06-20 21:45:16.000000000 +0100
@@ -3701,7 +3701,7 @@
 		flags = SE_FREE;
 	} else {
 		convert_to_long_ex(search_flags);
-		flags = Z_LVAL_PP(search_flags);
+		flags = Z_LVAL_PP(search_flags) & SE_FREE;
 		if (argc == 4) {
 			convert_to_string_ex(charset);
 		}
@@ -3712,10 +3712,6 @@
 
 	mail_search_full(imap_le_struct->imap_stream, (argc == 4 ? Z_STRVAL_PP(charset) : NIL), pgm, flags);
 
-	if (pgm) {
-		mail_free_searchpgm(&pgm);
-	}
-
 	if (IMAPG(imap_messages) == NIL) {
 		efree(search_criteria);
 		RETURN_FALSE;
 [2009-06-20 21:15 UTC] pajoye@php.net
I made one already too, http://pastebin.com/m22b58a19

I prefer this way as there is no ambiguity, I also fixed the other locations where a similar situation can happen.

I have to merge into head and it will committed.

Thanks for your work!
 [2009-06-20 21:26 UTC] andy at webtatic dot com
SE_FREE is also a PHP constant, so the user (for some reason), might pass in the flag SE_FREE | SE_UID, which a direct != will not match SE_FREE on, causing the same issue. You should probably do a bitwise check for the flag in your case.
 [2009-06-20 21:33 UTC] pajoye@php.net
Sorry, I should have been more clear, this patch is not tested (did not even compile it, no vc at hand :), it was only for the idea. Yes, the free mode is also a constant as well as some other, so a bit comparison is necessary. 

That being said, I'm not sure to understand why we exposed SE_FREE in the 1st place...
 [2009-06-20 21:36 UTC] andy at webtatic dot com
ah right ok.

yep, it doesn't really make sense to add in a constant that can only be used (or not used in this case) to create a memory leak.
 [2009-06-20 21:58 UTC] andy at webtatic dot com
sorry for intruding again, but I thought this patch might be more ideal for the imap_sort, as it'd be hard to compare the flag when its still in its PHP wrapper.

http://pastebin.com/m2325a4b4
 [2009-06-20 22:08 UTC] andy at webtatic dot com
oops, should have used | not & :) it prob makes a bit more sense then

http://pastebin.com/m33a7819b
 [2009-06-22 09:48 UTC] oeriksson at mandriva dot com
That patch did not help for me.
 [2009-06-22 12:01 UTC] pajoye@php.net
I still prefer the final version I was mentioning to avoid confusion in future changes. I will post it here again soon.
 [2009-06-22 12:28 UTC] pajoye@php.net
Segfault went away with:

http://pastebin.com/m56e61b1b

works whether SE_FREE is set or not. Tested with c-client 2007.
 [2009-06-22 21:44 UTC] pajoye@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sat Apr 19 17:01:54 2014 UTC