Greetings,

I recently upgraded to the latest PHP 5.3 snapshot and I found the following 
SoapClient bug:

<?php
ini_set("soap.wsdl_cache_enabled", 0);
new SoapClient("http://localhost/ws/catalog?wsdl";);
?>

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: 
Couldn't load from 'http://localhost/ws/catalog?wsdl' : Start tag expected, '<' 
not found


The problem turned out to be an invalid interpretation of the HTTP/1.1 protocol 
with "Transfer-Encoding: chunked" by the HTTP stream context, which caused 
get_sdl() to parse a WSDL including the chunk tags (hex numbers).

Chunked encoding is used by Apache 2.0 when "Content-Length" is unavailable, 
the data content being sent is large enough, and the protocol is HTTP/1.1.

I initially tried using readfile() but I didn't get the same problem. 
Eventually I could finally reproduce the bug with the following script:

<?php
$opts = array('http' => array('method' => "GET", 'header' => "Accept-language: 
en\r\nConnection: close\r\n"));
$context = stream_context_create($opts);
stream_context_set_option($context, "http", "protocol_version", 1.1);
fpassthru(fopen('http://localhost/ws/catalog?wsdl', 'r', false, $context));
?>

I can notice various problems here:

1) All the chunk tags are left in place and the extra newlines are not 
stripped, leading to corrupted data.

2) Without the "Connection: close" header the stream blocks until http timeout. 
It should instead detect the chunk with 0 bytes and return from the fpassthru().


In the meanwhile, the following patch is a workaround for the problem I had: it 
restores the default HTTP/1.0.

Side note: Shouldn't the last smart_str_appendl() call also contain an EOL?

Side note #2: Is there any way to avoid repeating the same string twice? It's 
very common in the soap extension and I think it's really error prone.

Side note #3: Is it possible to create a test for this bug? Like a raw HTTP/1.1 
response stored in a text file with chunk encoding and a script that loads that 
data...?


--- ext/soap/php_sdl.c.orig     2008-12-31 12:37:12.000000000 +0100
+++ ext/soap/php_sdl.c  2009-01-25 22:09:14.000000000 +0100
@@ -3192,14 +3192,16 @@
        basic_authentication(this_ptr, &headers TSRMLS_CC);
 
        /* Use HTTP/1.1 with "Connection: close" by default */
+#if 0
        if (php_stream_context_get_option(context, "http", "protocol_version", 
&tmp) == FAILURE) {
-       zval *http_version;
+               zval *http_version;
                MAKE_STD_ZVAL(http_version);
                ZVAL_DOUBLE(http_version, 1.1);
                php_stream_context_set_option(context, "http", 
"protocol_version", http_version);
                zval_ptr_dtor(&http_version);
                smart_str_appendl(&headers, "Connection: close", 
sizeof("Connection: close")-1);
        }
+#endif
 
        if (headers.len > 0) {
                zval *str_headers;




Regards

-- 
Giovanni Giacobbi

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to