Exakat 0.12.12 review

Exakat 0.12.12 review

Exakat 0.12.12 is out. Exakat has added some new analysis this week : support for ext/parle extension, help on pathinfo() usage, check on pathinfo() and array_values(). Exakat also includes getMessage() into the ‘don’t echo error message’, and ‘No concat in a loop’ covers new situations. Welcome to exakat 0.12.12!

echo getMessage() in catch clause

Following last week’s discussion on Twitter about wrong use of catch(), we upgraded the ‘Don’t echo error message’ analysis. Any situation which displays error messages is a security concern.

<?php
try { 
} catch(Exception $e) {
 echo mysqli_error();
 print socket_last_error();
 exit $e->getMessage();
 // Quite a nest of echo, isn't it? 
}
?>

Be aware that, besides getMessage(), one may also leak information with getStack() and getStackAsString(). As for ‘error functions’, there are about 110 PHP native function that give you access to errors, like zend_error(), xmlrpc_error(), preg_last_error(), date_get_last_errors() or oci_error().
This is a significant security mistake. While it doesn’t give access to any malicious party, it leaks a lot of interesting informations, usually leading to more attacks on your code. Avoid them at all cost.

pathinfo() usage

pathinfo() is a helper native function, that extract important pieces out of a path: file, extension, directory. By default, it reports everything available:

<?php
$path = '/path/to/file.ext';
print_r(pathinfo($path));
?>

This displays:
Array
(
[dirname] => /path/to
[basename] => file.ext
[extension] => ext
[filename] => file
)

Lesser know is the second argument: you may provide any of PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION or PATHINFO_FILENAME and get back a string, not an array. This way, it is much more efficient to write

<?php
$path = '/path/to/file.ext';
$filename = pathinfo($path, PATHINFO_FILENAME);
?>

Than

<?php
$path = '/path/to/file.ext';
$details = pathinfo($path);
$filename = $details['filename'];
?>

On top of that, PHP does less work when returning only one element of the path, and the first call is actually 50% faster than the second.
As long as you’re calling pathinfo() and using one or two of its element, using the 2nd argument is faster. Once there are 3 elements used, the array() version is better suited.

List() and array_values(pathinfo())

When all the values from pathinfo() are requested, it is tempting to use list() to assign them directly.

<?php
list($dirname, $basename, $extension, $filename) = array_values(pathinfo($file));

// PHP 7.1 is also possible: 
['dirname' => $dirname, 
 'basename' => $basename, 
 'extension' => $extension, 
 'filename' => $filename] = pathinfo($file);
?>

However, this approach has a main drawback : pathinfo() doesn’t always return four elements : sometimes, there is no extension (for README). In that case, ‘extension’ is omitted in pathinfo() return, and this leads to warnings, and even, bugs : $extension gets the filename and $filename is empty.

One may suggest that pathinfo() may be upgraded, to return a consistent array each time. That would be a solution. The other solution is to check for ‘extension’, and set it accordingly. This means, no array_values (or PHP 7.1 list()) for pathinfo().

Support for ext/parsle

Parle is actually Parser-Lexer extension, written by Anatol Belski. The Lexer turns a string into a serie of tokens, while the parser apply extra rules on the serie of token to build more complex structure.

For example, the lexer would read integers, out of a comma-separated list of them, while the parse would also identify real number, with the comma as a decimal separator.

See the docs at https://github.com/weltling/parle.

Happy PHP code reviews

All the 320+ analyzers are presented in the docs, including the visibility report, which check usage of constants, methods and properties and suggest any upgrade in visibility possible. See it in action on phpMailer’s code here. Download Exakat on exakat.io, upgrade it with ‘exakat.phar upgrade -u’ and like us on github: https://github.com/exakat/exakat.