From:             
Operating system: gentoo
PHP version:      5.3.6
Package:          cURL related
Bug Type:         Bug
Bug description:race condition: curlwapper is not sending http header randomly

Description:
------------
background: php is configured with curl wrapper, which make
file_get_contents 
use curl. i haven't tested with calling curl functions directly

php unset curl header too soon before curl make the request

expected order: set header, build and send request. unset header
actual order 1: set header, build and send request. unset header (good)
actual order 2: set header, unset header, build and send request (bad)
"send request" comes after php "unset header"
curl behavior randomly, by sending request before or after php unset the
header


Test script:
---------------
#!/usr/lib/php5.3/bin/php
<?php
for (;;) {
        $username = 'test1';
        $password = mt_rand(0, 99999) .
'....................................................................................';
        $authUrl = "http://localhost/";;
        $context = stream_context_create(array(
                                'http' => array(
                                        'header'  => "Authorization: Basic
" . base64_encode("$username:$password")
                                        )
                                ));
        $http_response_header = array();
        $data = file_get_contents($authUrl, false, $context);
        sleep(1);
}
?>

tcpdump -nilo dst port 80 -w- -s0

Expected result:
----------------
GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6MTQzNjEuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=

GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6NTY3MDQuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=


GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6MTQzNjEuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=

GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6NTY3MDQuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=


Actual result:
--------------
GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6MTQzNjEuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=

GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*
Authorization: Basic 
dGVzdDE6NTY3MDQuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u
Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4=

GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*


GET / HTTP/1.1
User-Agent: PHP/5.3.6-pl0-gentoo
Host: localhost
Accept: */*


gdb --args /usr/lib/php5.3/bin/php.debug test.php

(gdb) l
/usr/src/debug/dev-lang/php-5.3.6/sapis-build/cli/ext/curl/streams.c:367
360                                             slist =
curl_slist_append(slist, 
trimmed);
361                                             efree(trimmed);
362                                             p = php_strtok_r(NULL,
"\r\n", 
&token);
363                                     }
364                                     efree(copy_ctx_opt);
365                             }
366                             if (slist) {
367                                     curl_easy_setopt(curlstream->curl,

CURLOPT_HTTPHEADER, slist);
368                             }
369                     }
370                     if (SUCCESS ==
php_stream_context_get_option(context, 
"http", "method", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
371                             if (strcasecmp(Z_STRVAL_PP(ctx_opt),
"get")) {
372                                     if
(!strcasecmp(Z_STRVAL_PP(ctx_opt), 
"head")) {
373                                            
curl_easy_setopt(curlstream-
>curl, CURLOPT_NOBODY, 1);
374                                     } else {
(gdb) l
/usr/src/debug/dev-lang/php-5.3.6/sapis-build/cli/ext/curl/streams.c:501
494                     if (msg_found) {
495                             goto exit_fail;
496                     }
497             }
498
499             /* context headers are not needed anymore */
500             if (slist) {
501                     curl_easy_setopt(curlstream->curl,
CURLOPT_HTTPHEADER, 
NULL);
502                     curl_slist_free_all(slist);
503             }
504             return stream;
505
506     exit_fail:
507             php_stream_close(stream);
508             if (slist) {
(gdb) br 367
Breakpoint 1 at 0x1c59c9: file /usr/src/debug/dev-lang/php-5.3.6/sapis-
build/cli/ext/curl/streams.c, line 367.
(gdb) br 501
Breakpoint 2 at 0x1c61bc: file /usr/src/debug/dev-lang/php-5.3.6/sapis-
build/cli/ext/curl/streams.c, line 501.
(gdb) br Curl_send_plain
Breakpoint 4 at 0xb7698ca0: file sendf.c, line 279.


(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /usr/lib/php5.3/bin/php ./test
[Thread debugging using libthread_db enabled]
warning: Lowest section in /usr/lib/libicudata.so.48 is .hash at 000000f4
[New Thread 0xb55e76f0 (LWP 31857)]
[Switching to Thread 0xb55e76f0 (LWP 31857)]

Breakpoint 1, php_curl_stream_opener (wrapper=0x80aacd44,
filename=0x80c45c24 
"http://localhost/vbb/authapi.php";,
    mode=0x80a2a01b "rb", options=4, opened_path=0x0, context=0x80c47224)
    at
/usr/src/debug/dev-lang/php-5.3.6/sapis-build/cli/ext/curl/streams.c:367
367                                     curl_easy_setopt(curlstream->curl,

CURLOPT_HTTPHEADER, slist);
(gdb) c
Continuing.

Breakpoint 2, php_curl_stream_opener (wrapper=0x80aacd44,
filename=0x80c45c24 
"http://localhost/";,
    mode=0x80a2a01b "rb", options=4, opened_path=0x0, context=0x80c47224)
    at
/usr/src/debug/dev-lang/php-5.3.6/sapis-build/cli/ext/curl/streams.c:501
501                     curl_easy_setopt(curlstream->curl,
CURLOPT_HTTPHEADER, 
NULL);
(gdb) c
Continuing.

Breakpoint 4, Curl_send_plain (conn=0x80cd0628, num=0, mem=0x80cd1120,
len=82, 
code=0xbff162f4) at sendf.c:279
279     {

(gdb) p ((char*)mem)[0]@len
$1 = "GET /vbb/authapi.php HTTP/1.1\r\nUser-Agent:
PHP/5.3.6-pl0-gentoo\r\nHost: 
localhost\r\nAccept: */*\r\n\r\n"

Authorization header is not there

===========================
to reproduce this bug, curl is built with ares and without threads
(in another case http request is not even send, when curl is built with
threads 
and without ares, was a curl issue i guess)

# equery uses net-misc/curl
[ Legend : U - final flag setting for installation]
[        : I - package is installed with flag     ]
[ Colors : set, unset                             ]
 * Found these USE flags for net-misc/curl-7.21.4:
 U I
 + + ares        : Enabled c-ares dns support
 + + gnutls      : Prefer gnutls over nss and openssl as the crypto engine
 - - idn         : Enable support for Internationalized Domain Names
 + + ipv6        : Adds support for IP version 6
 + + kerberos    : Adds kerberos support
 - - ldap        : Adds LDAP support (Lightweight Directory Access
Protocol)
 - - libssh2     : Enabled SSH urls in curl using libssh2
 - - nss         : Prefer NSS over openssl as the crypto engine
 + + ssl         : Enable crypto engine support (via openssl if
USE='-gnutls -
nss')
 - - static-libs : Build static libraries
 - - test        : Workaround to pull in packages needed to run with 
FEATURES=test. Portage-2.1.2 handles this internally,
                   so don't set it in make.conf/package.use anymore
 - - threads     : Adds threads support for various packages. Usually
pthreads


-- 
Edit bug report at https://bugs.php.net/bug.php?id=55438&edit=1
-- 
Try a snapshot (PHP 5.4):            
https://bugs.php.net/fix.php?id=55438&r=trysnapshot54
Try a snapshot (PHP 5.3):            
https://bugs.php.net/fix.php?id=55438&r=trysnapshot53
Try a snapshot (trunk):              
https://bugs.php.net/fix.php?id=55438&r=trysnapshottrunk
Fixed in SVN:                        
https://bugs.php.net/fix.php?id=55438&r=fixed
Fixed in SVN and need be documented: 
https://bugs.php.net/fix.php?id=55438&r=needdocs
Fixed in release:                    
https://bugs.php.net/fix.php?id=55438&r=alreadyfixed
Need backtrace:                      
https://bugs.php.net/fix.php?id=55438&r=needtrace
Need Reproduce Script:               
https://bugs.php.net/fix.php?id=55438&r=needscript
Try newer version:                   
https://bugs.php.net/fix.php?id=55438&r=oldversion
Not developer issue:                 
https://bugs.php.net/fix.php?id=55438&r=support
Expected behavior:                   
https://bugs.php.net/fix.php?id=55438&r=notwrong
Not enough info:                     
https://bugs.php.net/fix.php?id=55438&r=notenoughinfo
Submitted twice:                     
https://bugs.php.net/fix.php?id=55438&r=submittedtwice
register_globals:                    
https://bugs.php.net/fix.php?id=55438&r=globals
PHP 4 support discontinued:          
https://bugs.php.net/fix.php?id=55438&r=php4
Daylight Savings:                    https://bugs.php.net/fix.php?id=55438&r=dst
IIS Stability:                       
https://bugs.php.net/fix.php?id=55438&r=isapi
Install GNU Sed:                     
https://bugs.php.net/fix.php?id=55438&r=gnused
Floating point limitations:          
https://bugs.php.net/fix.php?id=55438&r=float
No Zend Extensions:                  
https://bugs.php.net/fix.php?id=55438&r=nozend
MySQL Configuration Error:           
https://bugs.php.net/fix.php?id=55438&r=mysqlcfg

Reply via email to