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