|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[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 ()
Patchessoapfault-patch-1 (last revision 2013-06-06 07:07 UTC by andreas dot lindemann at de dot bp dot com)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 07:00:01 2025 UTC |
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);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?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?