php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64233 Soapserver::fault bus error on Solaris CLI/CGI/FPM
Submitted: 2013-02-18 09:52 UTC Modified: 2013-06-11 09:42 UTC
Votes:5
Avg. Score:5.0 ± 0.0
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: andreas dot lindemann at de dot bp dot com Assigned:
Status: Closed Package: SOAP related
PHP Version: 5.4.11 OS: Solaris 10
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: andreas dot lindemann at de dot bp dot com
New email:
PHP Version: OS:

 

 [2013-02-18 09:52 UTC] andreas dot lindemann at de dot bp dot com
Description:
------------
Reproducably received a bus error/core dump when returning a Soapfault from the 
Soapserver on Solaris.

Tried different execution paths and could reproduce on all of them:

1) PHP-CGI via Apache/mod_fcgid
2) PHP-FPM as backend for nginx
3) PHP-CLI from command line

$ php -f test_script.php
Bus Error (core dumped)

$ uname -a
SunOS testhost 5.10 Generic_147440-10 sun4u sparc SUNW,SPARC-Enterprise

$ php -v
PHP 5.4.11 (cli) (built: Feb  2 2013 12:02:33)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

$ php -m
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dom
ereg
filter
ftp
gd
iconv
json
ldap
libxml
mbstring
oci8
openssl
pcntl
pcre
PDO
posix
Reflection
session
SimpleXML
soap
sockets
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlrpc
xsl
zip
zlib


Test script:
---------------
<?php
  $options['uri'] = 'urn:someNamespace';
  $server = new SoapServer(null, $options);
  $server->fault("Server", "message"); // <- Bus error, core Dumped


Expected result:
----------------
A correctly generated Soap XML response.

Actual result:
--------------
Program terminated with signal 10, Bus error.

Backtrace: 
#0  0x00000001003d0654 in php_escape_html_entities_ex ()
#1  0x00000001003cf830 in php_escape_html_entities ()
#2  0x00000001002dc170 in serialize_response_call ()
#3  0x00000001002d1954 in soap_server_fault_ex ()
#4  0x00000001002d1c88 in soap_server_fault ()
#5  0x00000001002d150c in zim_SoapServer_fault ()
#6  0x00000001005ae62c in zend_do_fcall_common_helper_SPEC ()
#7  0x00000001005af5fc in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER ()
#8  0x00000001005acc50 in execute ()
#9  0x000000010055e2e4 in zend_execute_scripts ()
#10 0x0000000100495f60 in php_execute_script ()
#11 0x00000001006c8294 in main ()


Patches

soapfault-patch-1 (last revision 2013-06-06 07:07 UTC by andreas dot lindemann at de dot bp dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-02-18 10:06 UTC] andreas dot lindemann at de dot bp dot com
Note PHP has been compiled with 64bit.
 [2013-02-18 12:47 UTC] andreas dot lindemann at de dot bp dot com
Tried to reproduce on older versions: 5.4.6 fails with same error.

PHP 5.3.21 however works correctly:

$ ./php -v
PHP 5.3.21 (cli) (built: Feb 18 2013 13:16:03)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies

$ ./php -f test_script.php
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode>
<faultstring>SoapServer::SoapServer(): Invalid parameters</faultstring></SOAP-
ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

Something must have been broken between 5.3.21 and 5.4.6+, maybe this helps with 
the investigation.
 [2013-02-21 05:34 UTC] laruence@php.net
no luck to reproduce this on centOS.
 [2013-02-21 06:09 UTC] andreas dot lindemann at de dot bp dot com
This may be specific to Solaris 64bit. 
I tried to reproduce on Linux 64bit (SuSE Linux Enterprise), but no issue there as well. 
However no problem to reproduce this on 5 of our Solaris Sparc servers, all are showing the same bus error and backtrace.
 [2013-03-19 09:29 UTC] andreas dot lindemann at de dot bp dot com
Any chance of fixing or reproducing this?
If I can be of assistance, i.e. running some debug build to give more insight into the issue or so, please let me know.

For now I've made a change to the soap extension to not run through the php_escape_html_entities_ex function. This is probably neither a good idea nor anywhere near a proper fix, considering that I've only got a very basic idea of C, but at least it throws the SoapFaults correctly to the client and doesn't crash the PHP process.

--- ext/soap/soap.c.orig        2013-01-16 08:10:30.000000000 +0100
+++ ext/soap/soap.c     2013-03-11 12:30:34.497971000 +0100
@@ -3881,7 +3881,8 @@
                        if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
                                int new_len;
                                xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
-                               char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
+                               char *str = (unsigned char*)Z_STRVAL_PP(tmp);
                                xmlAddChild(param, node);
                                if (fault_ns) {
                                        xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
@@ -3906,7 +3907,8 @@
                        if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
                                int new_len;
                                xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Code"), NULL);
-                               char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
+                               char *str = (unsigned char*)Z_STRVAL_PP(tmp);
                                node = xmlNewChild(node, ns, BAD_CAST("Value"), NULL);
                                if (fault_ns) {
                                        xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
 [2013-05-27 06:49 UTC] andreas dot lindemann at de dot bp dot com
Now with php 5.4.14 and still trying to narrow this down.
So far, I've narrowed it down to a single line of code.
The issue seems to be caused in ext/standard/html.c at the very end of php_escape_html_entities_ex():

    replaced[len] = '\0';   // This seems to be fine
    *newlen = len;          // <-- This line crashes PHP

    return replaced;
}

It seems the issue occurs when accessing the "len" variable. If I add another line just before the *newlen = len; line, i.e. for getting the value of "len" out to the php logfile, PHP crashes on that new line as well:

Example (not a nice one):

            php_error_docref0(NULL TSRMLS_CC, E_STRICT, "debug 1");
    replaced[len] = '\0';
// Next line still goes to the log
            php_error_docref0(NULL TSRMLS_CC, E_STRICT, "debug 2");
// Next line crashes PHP
            php_error_docref0(NULL TSRMLS_CC, E_STRICT, (char*)len);
// This won't be executed:
    *newlen = len;
// And we'll never see this:
            php_error_docref0(NULL TSRMLS_CC, E_STRICT, "debug 3");

    return replaced;
}

Any ideas?
 [2013-05-27 10:12 UTC] andreas dot lindemann at de dot bp dot com
Seem to have found the main issue.

"new_len" is defined int in ext/soap/soap.c in function serialize_response_call:

int new_len;
xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);

However, php_escape_html_entities() handles new_len as size_t.

PHPAPI char *php_escape_html_entities(unsigned char *old, size_t oldlen, size_t *newlen, int all, int flags, char *hint_charset TSRMLS_DC)

php_escape_html_entities_ex() tracks the string length in a 

size_t len

When assigning the size_t value to the int pointer, PHP crashes.
This can be reproduced by a very simple C program on Solaris 64 bit which just replicates this process:

----------------------
#include <stdio.h>

int testfunc(size_t *dummy)
{
  size_t len;
  len = 5;

  *dummy = len;
}

int main()
{
  int test;

  testfunc(&test);

  return 0;
}
----------------------

$ gcc -m64 test.c
test.c: In function 'main':
test.c:15:3: warning: passing argument 1 of 'testfunc' from incompatible pointer type [enabled by default]
test.c:3:5: note: expected 'size_t *' but argument is of type 'int *'

$ ./a.out
Bus Error (core dumped)

Note: On 64-bit Linux, this program runs without errors! So you cannot reproduce this issue on Linux!

There seem to be 2 ways to fix this:
1) Change new_len declaration to size_t in ext/soap/soap.c -> works fine, BUT new_len is also passed to xmlNodeSetContentLen, which expects this parameter to be int. Can use a cast to convert the size_t to int though, shouldn't matter unless your string exceeds MAX_INT?

2) Change php_escape_html_entities and php_escape_html_entities_ex in ext/standard/html.c to expect newlen as int and declare "len" as int as well.

To me, 1) sounds to be the easier solution which only impacts soap.c really, leaving other places where php_escape_html_entities is used untouched.

Sounds reasonable?
 [2013-06-11 09:41 UTC] andreas dot lindemann at de dot bp dot com
This seems to have been fixed in a commit on git for PHP 5.3:
https://github.com/php/php-src/commit/fe21accfb4913bf309f26894ae27e9ad34fb5260

From there it has been ported to PHP 5.4.

Why isn't this listed in the official Changelog for 5.3.26 and 5.4.16?
 [2013-06-11 09:42 UTC] andreas dot lindemann at de dot bp dot com
-Status: Open +Status: Closed
 [2013-06-11 09:42 UTC] andreas dot lindemann at de dot bp dot com
Fixed in versions 5.3.26 & 5.4.16 although not listed in Changelog.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 26 19:01:30 2024 UTC