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 (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.3.0RC3 OS: *
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: erik at datahack dot se
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC