3

I noticed that a file browser widget was taking considerably longer to load after moving from php 7.2 to 7.3.

An operation that normally takes under a second was taking considerably longer. After enabling slowlog I traced the issue to MIME lookups using finfo. After reverting to 7.2 the issue was resolved.

This is a simple test I created to illustrate the problem:

#!/bin/bash
set -e

ITERS=${1:-1000}

echo "Testing finfo over $ITERS iterations"
for VER in '7.2' '7.3'; do
        echo ---
        echo "Testing PHP $VER"
        docker run -i \
                -e "ITERS=${ITERS}" \
                php:${VER}-cli-alpine php <<'EOF'
<?php
$iters = $_ENV["ITERS"];

$start = microtime(true);
for ($i = 1; $i <= $iters; $i++){
  $finfo = new finfo(FILEINFO_MIME);
  $type = $finfo->file("/bin/sh");
  unset($finfo);
}
$ttl = microtime(true) - $start;
echo "Took: $ttl\n";
?>
EOF
done

Here is the result as run on a prestine DigitalOcean droplet with 3 CPUs:

root@phptest:~# ./test.sh 1000
Testing finfo over 1000 iterations
---
Testing PHP 7.2
Took: 1.2104759216309
---
Testing PHP 7.3
Took: 2.4543979167938

The 7.3 test took more than twice as long. I've run this test on a number of systems, and in all cases I see an increase in runtime for 7.3 of 30% or more; in some cases far more. This is the same test run on a droplet with more load and only 2 CPUs (this is the machine where I first encountered the problem; which you can see why):

% ./test.sh 100
Testing finfo over 100 iterations
---
Testing PHP 7.2
Took: 0.10123181343079
---
Testing PHP 7.3
Took: 34.721122980118

What could be the cause of this slowdown, and are there any configuration/optimizations that I should be employing?

1 Answers1

2

finfo is heavily dependent on PCRE, and in 7.3 they updated the PCRE library. I can not find any other changes in the changelog that may have had an effect to this extent.

If this is the case, there is nothing you can do about it, except to revert to 7.2 or use a different method for identifying mime type; or employ another security vector - finfo is actually very easily fooled, so isn't that great a solution anyway. See PHP file upload: mime or extension based verification? for a more in depth (and ranty) discussion and example.

Abulafia
  • 1,741
  • 12
  • 25
  • Thanks for confirming what I suspected. The widget that was using finfo appears to be doing so only to determine if the file is binary or not by checking if the first four characters of the MIME type are "text"... which seems like a pretty roundabout way of checking that to begin with. – Jake Scaltreto Jan 28 '19 at 21:15
  • No problem. It is a bit of a guess, but I had a go with your script for half an hour or so and it does seem the most likely explanation. Are you interested in filing a bug report? It certainly doesn't seem to be expected behaviour. – Abulafia Jan 28 '19 at 21:21