Mercurial > hg > isophonics-drupal-site
diff vendor/nikic/php-parser/doc/component/Constant_expression_evaluation.markdown @ 13:5fb285c0d0e3
Update Drupal core to 8.4.7 via Composer. Security update; I *think* we've
been lucky to get away with this so far, as we don't support self-registration
which seems to be used by the so-called "drupalgeddon 2" attack that 8.4.5
was vulnerable to.
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:33:26 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/nikic/php-parser/doc/component/Constant_expression_evaluation.markdown Mon Apr 23 09:33:26 2018 +0100 @@ -0,0 +1,115 @@ +Constant expression evaluation +============================== + +Initializers for constants, properties, parameters, etc. have limited support for expressions. For +example: + +```php +<?php +class Test { + const SECONDS_IN_HOUR = 60 * 60; + const SECONDS_IN_DAY = 24 * self::SECONDS_IN_HOUR; +} +``` + +PHP-Parser supports evaluation of such constant expressions through the `ConstExprEvaluator` class: + +```php +<?php + +use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; + +$evalutator = new ConstExprEvaluator(); +try { + $value = $evalutator->evaluateSilently($someExpr); +} catch (ConstExprEvaluationException $e) { + // Either the expression contains unsupported expression types, + // or an error occurred during evaluation +} +``` + +Error handling +-------------- + +The constant evaluator provides two methods, `evaluateDirectly()` and `evaluateSilently()`, which +differ in error behavior. `evaluateDirectly()` will evaluate the expression as PHP would, including +any generated warnings or Errors. `evaluateSilently()` will instead convert warnings and Errors into +a `ConstExprEvaluationException`. For example: + +```php +<?php + +use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; +use PhpParser\Node\{Expr, Scalar}; + +$evaluator = new ConstExprEvaluator(); + +// 10 / 0 +$expr = new Expr\BinaryOp\Div(new Scalar\LNumber(10), new Scalar\LNumber(0)); + +var_dump($evaluator->evaluateDirectly($expr)); // float(INF) +// Warning: Division by zero + +try { + $evaluator->evaluateSilently($expr); +} catch (ConstExprEvaluationException $e) { + var_dump($e->getPrevious()->getMessage()); // Division by zero +} +``` + +For the purposes of static analysis, you will likely want to use `evaluateSilently()` and leave +erroring expressions unevaluated. + +Unsupported expressions and evaluator fallback +---------------------------------------------- + +The constant expression evaluator supports all expression types that are permitted in constant +expressions, apart from the following: + + * `Scalar\MagicConst\*` + * `Expr\ConstFetch` (only null/false/true are handled) + * `Expr\ClassConstFetch` + +Handling these expression types requires non-local information, such as which global constants are +defined. By default, the evaluator will throw a `ConstExprEvaluationException` when it encounters +an unsupported expression type. + +It is possible to override this behavior and support resolution for these expression types by +specifying an evaluation fallback function: + +```php +<?php + +use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; +use PhpParser\Node\Expr; + +$evalutator = new ConstExprEvaluator(function(Expr $expr) { + if ($expr instanceof Expr\ConstFetch) { + return fetchConstantSomehow($expr); + } + if ($expr instanceof Expr\ClassConstFetch) { + return fetchClassConstantSomehow($expr); + } + // etc. + throw new ConstExprEvaluationException( + "Expression of type {$expr->getType()} cannot be evaluated"); +}); + +try { + $evalutator->evaluateSilently($someExpr); +} catch (ConstExprEvaluationException $e) { + // Handle exception +} +``` + +Implementers are advised to ensure that evaluation of indirect constant references cannot lead to +infinite recursion. For example, the following code could lead to infinite recursion if constant +lookup is implemented naively. + +```php +<?php +class Test { + const A = self::B; + const B = self::A; +} +``` \ No newline at end of file