Edit report at https://bugs.php.net/bug.php?id=64233&edit=1
ID: 64233 Comment by: andreas dot lindemann at de dot bp dot com Reported by: andreas dot lindemann at de dot bp dot com Summary: Soapserver::fault bus error on Solaris CLI/CGI/FPM Status: Open Type: Bug Package: SOAP related Operating System: Solaris 10 PHP Version: 5.4.11 Block user comment: N Private report: N New Comment: 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? Previous Comments: ------------------------------------------------------------------------ [2013-05-27 10:12:20] 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-05-27 06:49:23] 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-03-19 09:29:57] 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-02-21 06:09:23] 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-02-21 05:34:56] larue...@php.net no luck to reproduce this on centOS. ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=64233 -- Edit this bug report at https://bugs.php.net/bug.php?id=64233&edit=1