php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48590 SOAP Client (redirect loop)
Submitted: 2009-06-17 21:05 UTC Modified: 2010-01-05 02:28 UTC
Votes:9
Avg. Score:3.2 ± 1.1
Reproduced:6 of 8 (75.0%)
Same Version:3 (50.0%)
Same OS:2 (33.3%)
From: erik at datahack dot se Assigned: srinatar
Status: Closed Package: Reproducible crash
PHP Version: 5.3.0RC3 OS: *
Private report: No CVE-ID:
 [2009-06-17 21:05 UTC] erik at datahack dot se
Description:
------------
A SOAPClient can be stuck in a redirect loop (and in some cases crash). Other PHP functions have solved this by a default redirection limit of 20 redirects (maybe a php.ini setting) or a custom value of a stream context -> http -> max_redirects.

I provide two examples, one where PHP crashes after ~200 requests and one where it just loops forever.

Reproduce code:
---------------
redirection-loop.php:
<?php
 header("Location: /redirection-loop.php");
?>

client code (crashes):
<?
$context = stream_context_create(
 array('http' => array('max_redirects' => 3))
 );
$soap = new SOAPClient(NULL,
 array(
  'uri' => 'foo',
  'location' => 'http://example.com/redirection-loop.php',
  'stream_context' => $context,
 )
);
$soap->test();
?>

client code (never finishes):
<?
$soap = new SOAPClient(NULL,
 array(
  'uri' => 'foo',
  'location' => 'http://example.com/redirection-loop.php'
 )
);
$soap->test();
?>

Expected result:
----------------
I expect it to have a default limit of 20 but also respect the max_requests value in the stream context. If the limit is reached I would expect a SOAPFault with a similar error description as below.

When requesting the same file (redirection-loop.php) with file_get_contents() you get a warning and a empty result is returned.

Warning: file_get_contents(http://example.com/redirection-loop.php): failed to open stream: Redirection limit reached, aborting in Command line code on line 1

Actual result:
--------------
This is what happens if you specify a stream_context and tries to make it respect the max_requests (which is does not)...

(gdb) bt
#0  0x082e2c9e in php_stream_context_get_option (context=0xa2eb5b4, wrappername=0x85eb353 "socket", optionname=0x8623e2a "bindto", 
    optionvalue=0xbf866d04) at php-5.3.0RC3/main/streams/streams.c:2036
#1  0x082ef2e3 in php_tcp_sockop_set_option (stream=0xa2eac68, option=7, value=0, ptrparam=0xbf866dd0)
    at php-5.3.0RC3/main/streams/xp_socket.c:641
#2  0x082e27d2 in _php_stream_set_option (stream=0xa2eac68, option=7, value=0, ptrparam=0xbf866dd0)
    at php-5.3.0RC3/main/streams/streams.c:1175
#3  0x082ed90f in php_stream_xport_connect (stream=0xa2eac68, name=0xa2eac16 "example.com:80", namelen=16, asynchronous=0, 
    timeout=0xbf866e84, error_text=0xbf866e8c, error_code=0x0) at php-5.3.0RC3/main/streams/transports.c:230
#4  0x082edcca in _php_stream_xport_create (name=0xa2eac16 "example.org:80", namelen=16, options=12, flags=0, persistent_id=0x0, 
    timeout=0xbf866e84, context=0xa2eb5b4, error_string=0x0, error_code=0x0)
    at php-5.3.0RC3/main/streams/transports.c:143
#5  0x081d56c6 in make_http_soap_request (this_ptr=0xa2ea634, 
    buf=0xa35d5f0 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"foo\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:SOAP-ENC="..., buf_size=378, 
    location=0xa2eaa18 "http://example.com/redirection-loop.php", soapaction=0xa2eab9c "foo#test", soap_version=1, 
    buffer=0xa2eab1c, buffer_len=0xa2eab20) at php-5.3.0RC3/ext/soap/php_http.c:120
#6  0x081b41d0 in zim_SoapClient___doRequest (ht=5, return_value=0xa2eab1c, return_value_ptr=0xbf8673c8, this_ptr=0xa2ea634, 
    return_value_used=1) at php-5.3.0RC3/ext/soap/soap.c:3249

(gdb) f 0
#0  0x082e2c9e in php_stream_context_get_option (context=0xa2eb5b4, wrappername=0x85eb353 "socket", optionname=0x8623e2a "bindto", 
    optionvalue=0xbf866d04) at php-5.3.0RC3/main/streams/streams.c:2036
2036		if (FAILURE == zend_hash_find(Z_ARRVAL_P(context->options), (char*)wrappername, strlen(wrappername)+1, (void**)&wrapperhash)) {

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-06-17 21:11 UTC] erik at datahack dot se
The sample code has an extra comma after the "'stream_context' => $context,".
 [2009-09-10 15:08 UTC] sjoerd@php.net
Could reproduce with latest 5.3.
 [2010-01-05 02:28 UTC] srinatar@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

here is a patch that should address this issue

Index: ext/soap/php_http.c
===================================================================
--- ext/soap/php_http.c (revision 293128)
+++ ext/soap/php_http.c (working copy)
@@ -207,6 +207,7 @@
        int http_1_1;
        int http_status;
        int content_type_xml = 0;
+       long redirect_max = 20;
        char *content_encoding;
        char *http_msg = NULL;
        zend_bool old_allow_url_fopen;
@@ -283,6 +284,14 @@
                context = php_stream_context_from_zval(*tmp, 0);
        }
 
+       if (context && 
+               php_stream_context_get_option(context, "http", "max_redirects", &tmp) == SUCCESS) {
+               if (Z_TYPE_PP(tmp) != IS_STRING || !is_numeric_string(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &redirect_max, NULL, 1)) {
+                       if (Z_TYPE_PP(tmp) == IS_LONG)
+                               redirect_max = Z_LVAL_PP(tmp);
+               }
+       }
+
 try_again:
        if (phpurl == NULL || phpurl->host == NULL) {
          if (phpurl != NULL) {php_url_free(phpurl);}
@@ -1012,6 +1021,12 @@
                                }
                                phpurl = new_url;
 
+                               if (--redirect_max < 1) {
+                                       smart_str_free(&soap_headers_z);
+                                       add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL TSRMLS_CC);
+                                       return FALSE;
+                               }
+
                                goto try_again;
                        }
                }

 [2010-01-05 03:07 UTC] svn@php.net
Automatic comment from SVN on behalf of srinatar
Revision: http://svn.php.net/viewvc/?view=revision&revision=293131
Log: - Fixed bug #48590 (SoapClient does not honor max_redirects)
 [2010-01-05 19:25 UTC] svn@php.net
Automatic comment from SVN on behalf of srinatar
Revision: http://svn.php.net/viewvc/?view=revision&revision=293152
Log: - Addressing minor leak noticed while addressing bug #48590
 [2010-01-27 17:42 UTC] svn@php.net
Automatic comment from SVN on behalf of johannes
Revision: http://svn.php.net/viewvc/?view=revision&revision=294110
Log: merge r293131 - Fixed bug #48590 (SoapClient does not honor max_redirects)
(srinatar)
 [2010-02-03 18:38 UTC] svn@php.net
Automatic comment from SVN on behalf of pajoye
Revision: http://svn.php.net/viewvc/?view=revision&revision=294435
Log: - Addressing minor leak noticed while addressing bug #48590
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Wed Apr 16 10:02:09 2014 UTC