php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76010 Built in server slices the $_SERVER['REQUEST_URI'] value
Submitted: 2018-02-26 08:06 UTC Modified: 2018-03-16 07:32 UTC
Votes:2
Avg. Score:4.5 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (50.0%)
From: t dot gemza at secit dot pl Assigned:
Status: Open Package: Built-in web server
PHP Version: 7.2.2 OS: Windows 7 and 8 64bit
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: t dot gemza at secit dot pl
New email:
PHP Version: OS:

 

 [2018-02-26 08:06 UTC] t dot gemza at secit dot pl
Description:
------------
The built in server slices the $_SERVER['REQUEST_URI'] value as shown on examples below.

The problem is confirmed on Windows 7 and 8 64bit machines with following PHP versions:

VC15 x64 Non Thread Safe (2018-Jan-31 23:18:33)
http://windows.php.net/downloads/releases/php-7.2.2-nts-Win32-VC15-x64.zip

VC15 x64 Thread Safe (2018-Jan-31 23:18:51)
http://windows.php.net/downloads/releases/php-7.2.2-Win32-VC15-x64.zip

VC14 x64 Non Thread Safe (2018-Jan-31 23:22:44)
http://windows.php.net/downloads/releases/php-7.1.14-nts-Win32-VC14-x64.zip

VC14 x64 Thread Safe (2018-Jan-31 23:23:00)
http://windows.php.net/downloads/releases/php-7.1.14-Win32-VC14-x64.zip

The problem was also confirmed on machines with PHP 7.1.10 and 7.2.1 (XAMP).

The problem will never be 100% reproducable. In our tests the full REQUST_URI was returned in about 3% of all of the test script runs. So if you can not reproduce it try different PHP version and than back to the previously tested - it should appear.

Test script:
---------------
---- CODE START ----
<?php

echo $_SERVER['REQUEST_URI'];

---- CODE END ----

CURL command:

curl "http://127.0.0.1:8001/administrator/dealer/account/?draw=3^&columns^%^5B0^%^5D^%^5Bdata^%^5D=id^&columns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^%^5B0^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B0^%^5D^%^5Borderable^%^5D=true^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5B1^%^5D^%^5Bname^%^5D=^&columns^%^5B1^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B1^%^5D^%^5Borderable^%^5D=true^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B2^%^5D^%^5Bdata^%^5D=lastName^&columns^%^5B2^%^5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B2^%^5D^%^5Borderable^%^5D=true^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B3^%^5D^%^5Bdata^%^5D=address^&columns^%^5B3^%^5D^%^5Bname^%^5D=^&columns^%^5B3^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B3^%^5D^%^5Borderable^%^5D=true^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B4^%^5D^%^5Bdata^%^5D=postalCode^&columns^%^5B4^%^5D^%^5Bname^%^5D=^&columns^%^5B4^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B4^%^5D^%^5Borderable^%^5D=true^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B5^%^5D^%^5Bdata^%^5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

Expected result:
----------------
Whole request URI started with /administrator/dealer/account/?draw=3&...

Actual result:
--------------
C:\>curl "http://127.0.0.1:8001/administrator/dealer/account/?draw=3^&
columns^%^5B0^%^5D^%^5Bdata^%^5D=id^&columns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^
%^5B0^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B0^%^5D^%^5Borderable^%^5D=true^
&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B0^%^5D^%^5Bsear
ch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5
B1^%^5D^%^5Bname^%^5D=^&columns^%^5B1^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5
B1^%^5D^%^5Borderable^%^5D=true^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^
5D=^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B2^%^5D
^%^5Bdata^%^5D=lastName^&columns^%^5B2^%^5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%
^5Bsearchable^%^5D=true^&columns^%^5B2^%^5D^%^5Borderable^%^5D=true^&columns^%^5
B2^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5B
regex^%^5D=false^&columns^%^5B3^%^5D^%^5Bdata^%^5D=address^&columns^%^5B3^%^5D^%
^5Bname^%^5D=^&columns^%^5B3^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B3^%^5D^%
^5Borderable^%^5D=true^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&colu
mns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B4^%^5D^%^5Bdata
^%^5D=postalCode^&columns^%^5B4^%^5D^%^5Bname^%^5D=^&columns^%^5B4^%^5D^%^5Bsear
chable^%^5D=true^&columns^%^5B4^%^5D^%^5Borderable^%^5D=true^&columns^%^5B4^%^5D
^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%
^5D=false^&columns^%^5B5^%^5D^%^5Bdata^%^5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXX"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


Only the XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX are returned

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-02-26 08:10 UTC] t dot gemza at secit dot pl
I forgot to add.

The built in server was always run with a following command:

php.exe -S 127.0.0.1:8001
 [2018-02-27 03:02 UTC] mattficken@php.net
Thanks for all the info up front.

However, I can NOT reproduce this issue with 7.2.2-nts

The repro script you provided should be saved as index.php, correct?

That should either always work or always fail, not 3% of time.

Would you run curl with --verbose ? or use the `Live HTTP Headers` extension in Firefox?  Maybe curl isn't providing or receiving all the path?

Where is the XXXXX returned by curl? In the name of the file that curl creates or in the file that curl creates?
 [2018-02-27 12:33 UTC] t dot gemza at secit dot pl
I don't know why, but the same test execution in small part of runs returns valid results.

Yes, the file should be named index.php

The problem was previously spotted in a Symfony project which was runned on built in server on the PHP version provided by XAMP. But further debugging confirmed that it's not related to Symfony but to PHP.

CURL is only an example. The problem was confirmed on Google Chrome and Mozilla Firefox (both in newest versions).

The XXXXs are the output returned by the server

Check this:

The first execution returned the valid response, but the second and third returned only XXXXs.

C:\>
C:\>
C:\>curl "http://127.0.0.1:8001/administrator/dealer/account/?draw=3^&columns^%^
5B0^%^5D^%^5Bdata^%^5D=id^&columns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^%^5B0^%^5D
^%^5Bsearchable^%^5D=true^&columns^%^5B0^%^5D^%^5Borderable^%^5D=true^&columns^%
^5B0^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^
5Bregex^%^5D=false^&columns^%^5B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5B1^%^5D^%^
5Bname^%^5D=^&columns^%^5B1^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B1^%^5D^%^
5Borderable^%^5D=true^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&colum
ns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B2^%^5D^%^5Bdata^
%^5D=lastName^&columns^%^5B2^%^5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%^5Bsearcha
ble^%^5D=true^&columns^%^5B2^%^5D^%^5Borderable^%^5D=true^&columns^%^5B2^%^5D^%^
5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D
=false^&columns^%^5B3^%^5D^%^5Bdata^%^5D=address^&columns^%^5B3^%^5D^%^5Bname^%^
5D=^&columns^%^5B3^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B3^%^5D^%^5Borderab
le^%^5D=true^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B3^
%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B4^%^5D^%^5Bdata^%^5D=post
alCode^&columns^%^5B4^%^5D^%^5Bname^%^5D=^&columns^%^5B4^%^5D^%^5Bsearchable^%^5
D=true^&columns^%^5B4^%^5D^%^5Borderable^%^5D=true^&columns^%^5B4^%^5D^%^5Bsearc
h^%^5D^%^5Bvalue^%^5D=^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^
&columns^%^5B5^%^5D^%^5Bdata^%^5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX" -D -
HTTP/1.1 200 OK
Host: 127.0.0.1:8001
Connection: close
Content-type: text/html; charset=UTF-8

/administrator/dealer/account/?draw=3^&columns^%^5B0^%^5D^%^5Bdata^%^5D=id^&colu
mns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^%^5B0^%^5D^%^5Bsearchable^%^5D=true^&colu
mns^%^5B0^%^5D^%^5Borderable^%^5D=true^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^5Bv
alue^%^5D=^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5
B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5B1^%^5D^%^5Bname^%^5D=^&columns^%^5B1^%^5
D^%^5Bsearchable^%^5D=true^&columns^%^5B1^%^5D^%^5Borderable^%^5D=true^&columns^
%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%
^5Bregex^%^5D=false^&columns^%^5B2^%^5D^%^5Bdata^%^5D=lastName^&columns^%^5B2^%^
5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B2^%^
5D^%^5Borderable^%^5D=true^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&
columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B3^%^5D^%^5B
data^%^5D=address^&columns^%^5B3^%^5D^%^5Bname^%^5D=^&columns^%^5B3^%^5D^%^5Bsea
rchable^%^5D=true^&columns^%^5B3^%^5D^%^5Borderable^%^5D=true^&columns^%^5B3^%^5
D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bregex^
%^5D=false^&columns^%^5B4^%^5D^%^5Bdata^%^5D=postalCode^&columns^%^5B4^%^5D^%^5B
name^%^5D=^&columns^%^5B4^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B4^%^5D^%^5B
orderable^%^5D=true^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns
^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B5^%^5D^%^5Bdata^%^
5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\>
C:\>
C:\>curl "http://127.0.0.1:8001/administrator/dealer/account/?draw=3^&columns^%^
5B0^%^5D^%^5Bdata^%^5D=id^&columns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^%^5B0^%^5D
^%^5Bsearchable^%^5D=true^&columns^%^5B0^%^5D^%^5Borderable^%^5D=true^&columns^%
^5B0^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^
5Bregex^%^5D=false^&columns^%^5B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5B1^%^5D^%^
5Bname^%^5D=^&columns^%^5B1^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B1^%^5D^%^
5Borderable^%^5D=true^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&colum
ns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B2^%^5D^%^5Bdata^
%^5D=lastName^&columns^%^5B2^%^5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%^5Bsearcha
ble^%^5D=true^&columns^%^5B2^%^5D^%^5Borderable^%^5D=true^&columns^%^5B2^%^5D^%^
5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D
=false^&columns^%^5B3^%^5D^%^5Bdata^%^5D=address^&columns^%^5B3^%^5D^%^5Bname^%^
5D=^&columns^%^5B3^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B3^%^5D^%^5Borderab
le^%^5D=true^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B3^
%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B4^%^5D^%^5Bdata^%^5D=post
alCode^&columns^%^5B4^%^5D^%^5Bname^%^5D=^&columns^%^5B4^%^5D^%^5Bsearchable^%^5
D=true^&columns^%^5B4^%^5D^%^5Borderable^%^5D=true^&columns^%^5B4^%^5D^%^5Bsearc
h^%^5D^%^5Bvalue^%^5D=^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^
&columns^%^5B5^%^5D^%^5Bdata^%^5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX" -D -
HTTP/1.1 200 OK
Host: 127.0.0.1:8001
Connection: close
Content-type: text/html; charset=UTF-8

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\>
C:\>
C:\>curl "http://127.0.0.1:8001/administrator/dealer/account/?draw=3^&columns^%^
5B0^%^5D^%^5Bdata^%^5D=id^&columns^%^5B0^%^5D^%^5Bname^%^5D=^&columns^%^5B0^%^5D
^%^5Bsearchable^%^5D=true^&columns^%^5B0^%^5D^%^5Borderable^%^5D=true^&columns^%
^5B0^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B0^%^5D^%^5Bsearch^%^5D^%^
5Bregex^%^5D=false^&columns^%^5B1^%^5D^%^5Bdata^%^5D=name^&columns^%^5B1^%^5D^%^
5Bname^%^5D=^&columns^%^5B1^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B1^%^5D^%^
5Borderable^%^5D=true^&columns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&colum
ns^%^5B1^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B2^%^5D^%^5Bdata^
%^5D=lastName^&columns^%^5B2^%^5D^%^5Bname^%^5D=^&columns^%^5B2^%^5D^%^5Bsearcha
ble^%^5D=true^&columns^%^5B2^%^5D^%^5Borderable^%^5D=true^&columns^%^5B2^%^5D^%^
5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B2^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D
=false^&columns^%^5B3^%^5D^%^5Bdata^%^5D=address^&columns^%^5B3^%^5D^%^5Bname^%^
5D=^&columns^%^5B3^%^5D^%^5Bsearchable^%^5D=true^&columns^%^5B3^%^5D^%^5Borderab
le^%^5D=true^&columns^%^5B3^%^5D^%^5Bsearch^%^5D^%^5Bvalue^%^5D=^&columns^%^5B3^
%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^&columns^%^5B4^%^5D^%^5Bdata^%^5D=post
alCode^&columns^%^5B4^%^5D^%^5Bname^%^5D=^&columns^%^5B4^%^5D^%^5Bsearchable^%^5
D=true^&columns^%^5B4^%^5D^%^5Borderable^%^5D=true^&columns^%^5B4^%^5D^%^5Bsearc
h^%^5D^%^5Bvalue^%^5D=^&columns^%^5B4^%^5D^%^5Bsearch^%^5D^%^5Bregex^%^5D=false^
&columns^%^5B5^%^5D^%^5Bdata^%^5D=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX" -D -
HTTP/1.1 200 OK
Host: 127.0.0.1:8001
Connection: close
Content-type: text/html; charset=UTF-8

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C:\>
C:\>
C:\>
 [2018-02-27 19:21 UTC] mattficken@php.net
Have you tried this on multiple machines?  

What language is Windows set to display?
 [2018-03-13 01:27 UTC] mattficken@php.net
Ping?
 [2018-03-13 01:28 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2018-03-16 07:32 UTC] t dot gemza at secit dot pl
-Status: Feedback +Status: Open
 [2018-03-16 07:32 UTC] t dot gemza at secit dot pl
Sorry for long response time. I'm out of office and don't have access to the problematic instances since next week. Currently I'm working on Mac and I don't have such problems here.

On all machines Windows is set to Polish language (pl_PL)
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Oct 28 03:01:23 2020 UTC