1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-21 22:32:41 +01:00

Fix ArcanistFormattedStringXHPASTLinterRule for PHP 8

Summary:
PHP 8's sprintf raises a ValueError when encountering unknown format
specifiers (previously it would eat the argument and print nothing), so
linting format strings like %Ls dies with an uncaught ValueError.

Fix this by using a custom callback during linting to turn all format
specifiers into %s and replace the dummy null argument with the original
format specifier, ensuring we always end up providing valid input to the
sprintf at the end. This has the nice property that the output of the
call to xsprintf is the original format string, though any
transformation into valid input would do.

Test Plan: Ran arc lint

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin

Maniphest Tasks: T13588

Differential Revision: https://secure.phabricator.com/D21500
This commit is contained in:
Jessica Clarke 2021-01-11 04:04:59 +00:00 committed by jrtc27
parent 0adef03fdf
commit 90ac9a2ff2

View file

@ -94,7 +94,10 @@ final class ArcanistFormattedStringXHPASTLinterRule
$argv = array($format->evalStatic()) + array_fill(0, $argc, null); $argv = array($format->evalStatic()) + array_fill(0, $argc, null);
try { try {
xsprintf(null, null, $argv); xsprintf(
'ArcanistFormattedStringXHPASTLinterRule::processXsprintfCallback',
null,
$argv);
} catch (BadFunctionCallException $ex) { } catch (BadFunctionCallException $ex) {
$this->raiseLintAtNode( $this->raiseLintAtNode(
$call, $call,
@ -105,4 +108,23 @@ final class ArcanistFormattedStringXHPASTLinterRule
} }
} }
public static function processXsprintfCallback(
$userdata,
&$pattern,
&$pos,
&$value,
&$length) {
if ($value !== null) {
throw new Exception('Expected dummy value to be null');
}
// Turn format "%$pattern" with argument null into format "%s" with
// argument "%$pattern". This ensures we always provide valid input for
// sprintf to avoid getting a ValueError when using custom format
// specifiers.
$value = '%'.$pattern[$pos];
$pattern[$pos] = 's';
}
} }