PHP stream_copy_to_stream() to php output corrupts data - the problem is SPECIFIC to Azure PHP Linux webapp service

79848876 11 Reputation points
2022-08-03T15:01:54.033+00:00

The bug exists on new Azure PHP 8 app service on Linux (nginx) ONLY. The same code works perfectly on Azure PHP on Windows and on local installations.

In a very short summary, if you try to use stream_copy_to_stream() to output to standard PHP output, it strips/loses first 117 bytes. stream_copy_to_stream() is a standard PHP function and as such used by many frameworks (Symfony, Laravel) - all those are affected. The problem was tested on other platforms and could not be reproduced.

Below is a shortest reproducer - it includes a verification code to prove that it it the actual function which is broken. The test is written by https://github.com/javierreguillo. The binary file must be at least 8,192 bytes in length.

First - this code DOES NOT work

$srcFile = './downloads/apple-touch-icon-180x180.png';  
  
$src = fopen($srcFile, 'r');  
$out = fopen('php://output', 'w');  
  
stream_copy_to_stream($src, $out);  
  
fclose($src);  
fclose($out);  

This code, on the other hand, works perfectly

$srcFile = './downloads/apple-touch-icon-180x180.png';  
  
$src = fopen($srcFile, 'r');  
$out = fopen('php://output', 'w');  
  
$size = 0;  
while (!feof($src)) {  
    $size += fwrite($out, fread($src, 8192));  
}  
  
fclose($src);  
fclose($out);  

The file below illustrates the output from both - as you could see stream_copy_to_stream($src, $out) strips first 117 bytes.
There is no workaround - the only way to fix it is not to use stream_copy_to_stream(). Unfortunately, it is an extremely common function which is baked into many 3rd party libraries which are subsequently broken.

227640-182589789-3a5df6b4-b3fe-4ed0-8fc9-0265eefe8be4.png

Azure App Service
Azure App Service
Azure App Service is a service used to create and deploy scalable, mission-critical web apps.
7,069 questions
{count} votes

1 answer

Sort by: Most helpful
  1. VenkateshDodda-MSFT 19,396 Reputation points Microsoft Employee
    2022-08-25T08:02:55.63+00:00

    @79848876 @Javier Reguillo @ab-oe Thank you for the patience on this. Our product team has investigated this issue and Based on your requirement/setup, you may try the following workaround:

    • Potential work-around is Set a custom docker image: az webapp config container set --name "your-site-name" --resource-group "your-resource-group" --docker-custom-image-name "mcr.microsoft.com/appsvc/php:8.0-apache_20220805.1.tuxprod"
      Note: this image takes about 6 to 7 minutes to pull.

    Warning: If you use the above work-around, you must remove the work-around after App Service has upgraded to version 99.0.0.0 or higher.

    From the Kudu (SCM) site, Select "Environment", and look for the PLATFORM_VERSION environment variable.The major version (first number in the 4-number version string) e.g. "99.0.7.577" if you see the major version as 99 or 100 you should remove the custom container config, make sure to set the App Setting WEBSITES_DISABLE_FPM=true, and change back to specifying PHP 8.x as the stack

    234776-image.png

    The following three commands are the instructions to remove the above workaround:

      az webapp config container delete --name <app-name> --resource-group<resource-group-name>       
    az webapp config appsettings set --name <app-name> --resource-group <group-name> --settings WEBSITES_DISABLE_FPM="true"      
    az webapp config set --resource-group <resource-group-name> --name <app-name> --linux-fx-version "PHP|8.0"  
    

    Feel Free to reach back to me if you have any further questions on this.

    1 person found this answer helpful.