From: kristijonas dot siaulys at delfi dot lt
Operating system: FreeBSD 5.1, RedHat 7.3
PHP version: Irrelevant
PHP Bug Type: Reproducible crash
Bug description: Apache crashes when non rfc2047 string is passed to
imap_mime_header_decode
Description:
------------
imap_mime_header_decode can't handle RFC2047 encoded strings where
encoding is not 'Q' or 'B' (qprint, base64).
If another letter is specified then Apache exits on signal 6. This is due
to usage of fs_give() where it shouldn't be.
The bug is located in ext/imap/php_imap.c.
As I've noticed all PHP versions suppoting imap_mime_header_decode funcion
have this bug.
Here is a fix patch:
--- ext/imap/php_imap.c.orig Thu Sep 4 10:48:30 2003
+++ ext/imap/php_imap.c Wed Jan 14 19:23:09 2004
@@ -3511,6 +3511,7 @@
char *string, *charset, encoding, *text, *decode;
long charset_token, encoding_token, end_token, end, offset=0, i;
unsigned long newlength;
+ int valid_encoding;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE)
{
ZEND_WRONG_PARAM_COUNT();
@@ -3550,11 +3551,14 @@
memcpy(text, &string[encoding_token +
3], end_token -
(encoding_token + 3)); /* Extract text */
text[end_token - (encoding_token + 3)]
= 0x00;
decode = text;
+ valid_encoding=0;
if (encoding == 'q' || encoding ==
'Q') { /* Decode 'q' encoded
data */
for(i=0; text[i] != 0x00; i++)
if (text[i] == '_') text[i] = '
'; /* Replace all *_' with space. */
decode = (char
*)rfc822_qprint((unsigned char *) text,
strlen(text), &newlength);
+ valid_encoding=1;
} else if (encoding == 'b' || encoding
== 'B') {
decode = (char
*)rfc822_base64((unsigned char *) text,
strlen(text), &newlength); /* Decode 'B' encoded data */
+ valid_encoding=1;
}
if (decode == NULL) {
efree(charset);
@@ -3566,7 +3570,7 @@
add_property_string(myobject,
"charset", charset, 1);
add_property_string(myobject, "text",
decode, 1);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void
*)&myobject, sizeof(zval *), NULL);
- fs_give((void**)&decode);
+ if(valid_encoding)
fs_give((void**)&decode);
offset = end_token+2;
for (i = 0; (string[offset + i] == '
') || (string[offset + i] ==
0x0a) || (string[offset + i] == 0x0d); i++);
Reproduce code:
---------------
imap_mime_header_decode("=?whatever?not_q_or_b?whatever?=");
As this function is mostly used in webmail systems to decode subjects, by
sending an email with malicious subject can make users mailbox
innacessible via that webmail application (as message subject listing
would crash apache).
Expected result:
----------------
I expect this function to decode text 'whatever' to 'whatever' and not to
crash Apache.
The code does that, but double 'free' at the end crashes Apache and no
resut is returned.
Actual result:
--------------
Apache child exited on signal 6.
This is beacuse such malformed string causes such code sequence (in
ext/imap/php_imap.c):
1. text = emalloc(size);
2. decoded = text;
3. fs_give(decoded);
4. efree(text);
notice two 'free' at the end.
--
Edit bug report at http://bugs.php.net/?id=26909&edit=1
--
Try a CVS snapshot (php4): http://bugs.php.net/fix.php?id=26909&r=trysnapshot4
Try a CVS snapshot (php5): http://bugs.php.net/fix.php?id=26909&r=trysnapshot5
Fixed in CVS: http://bugs.php.net/fix.php?id=26909&r=fixedcvs
Fixed in release: http://bugs.php.net/fix.php?id=26909&r=alreadyfixed
Need backtrace: http://bugs.php.net/fix.php?id=26909&r=needtrace
Need Reproduce Script: http://bugs.php.net/fix.php?id=26909&r=needscript
Try newer version: http://bugs.php.net/fix.php?id=26909&r=oldversion
Not developer issue: http://bugs.php.net/fix.php?id=26909&r=support
Expected behavior: http://bugs.php.net/fix.php?id=26909&r=notwrong
Not enough info: http://bugs.php.net/fix.php?id=26909&r=notenoughinfo
Submitted twice: http://bugs.php.net/fix.php?id=26909&r=submittedtwice
register_globals: http://bugs.php.net/fix.php?id=26909&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=26909&r=php3
Daylight Savings: http://bugs.php.net/fix.php?id=26909&r=dst
IIS Stability: http://bugs.php.net/fix.php?id=26909&r=isapi
Install GNU Sed: http://bugs.php.net/fix.php?id=26909&r=gnused
Floating point limitations: http://bugs.php.net/fix.php?id=26909&r=float