Mercurial > hg > isophonics-drupal-site
comparison 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 |
comparison
equal
deleted
inserted
replaced
12:7a779792577d | 13:5fb285c0d0e3 |
---|---|
1 Constant expression evaluation | |
2 ============================== | |
3 | |
4 Initializers for constants, properties, parameters, etc. have limited support for expressions. For | |
5 example: | |
6 | |
7 ```php | |
8 <?php | |
9 class Test { | |
10 const SECONDS_IN_HOUR = 60 * 60; | |
11 const SECONDS_IN_DAY = 24 * self::SECONDS_IN_HOUR; | |
12 } | |
13 ``` | |
14 | |
15 PHP-Parser supports evaluation of such constant expressions through the `ConstExprEvaluator` class: | |
16 | |
17 ```php | |
18 <?php | |
19 | |
20 use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; | |
21 | |
22 $evalutator = new ConstExprEvaluator(); | |
23 try { | |
24 $value = $evalutator->evaluateSilently($someExpr); | |
25 } catch (ConstExprEvaluationException $e) { | |
26 // Either the expression contains unsupported expression types, | |
27 // or an error occurred during evaluation | |
28 } | |
29 ``` | |
30 | |
31 Error handling | |
32 -------------- | |
33 | |
34 The constant evaluator provides two methods, `evaluateDirectly()` and `evaluateSilently()`, which | |
35 differ in error behavior. `evaluateDirectly()` will evaluate the expression as PHP would, including | |
36 any generated warnings or Errors. `evaluateSilently()` will instead convert warnings and Errors into | |
37 a `ConstExprEvaluationException`. For example: | |
38 | |
39 ```php | |
40 <?php | |
41 | |
42 use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; | |
43 use PhpParser\Node\{Expr, Scalar}; | |
44 | |
45 $evaluator = new ConstExprEvaluator(); | |
46 | |
47 // 10 / 0 | |
48 $expr = new Expr\BinaryOp\Div(new Scalar\LNumber(10), new Scalar\LNumber(0)); | |
49 | |
50 var_dump($evaluator->evaluateDirectly($expr)); // float(INF) | |
51 // Warning: Division by zero | |
52 | |
53 try { | |
54 $evaluator->evaluateSilently($expr); | |
55 } catch (ConstExprEvaluationException $e) { | |
56 var_dump($e->getPrevious()->getMessage()); // Division by zero | |
57 } | |
58 ``` | |
59 | |
60 For the purposes of static analysis, you will likely want to use `evaluateSilently()` and leave | |
61 erroring expressions unevaluated. | |
62 | |
63 Unsupported expressions and evaluator fallback | |
64 ---------------------------------------------- | |
65 | |
66 The constant expression evaluator supports all expression types that are permitted in constant | |
67 expressions, apart from the following: | |
68 | |
69 * `Scalar\MagicConst\*` | |
70 * `Expr\ConstFetch` (only null/false/true are handled) | |
71 * `Expr\ClassConstFetch` | |
72 | |
73 Handling these expression types requires non-local information, such as which global constants are | |
74 defined. By default, the evaluator will throw a `ConstExprEvaluationException` when it encounters | |
75 an unsupported expression type. | |
76 | |
77 It is possible to override this behavior and support resolution for these expression types by | |
78 specifying an evaluation fallback function: | |
79 | |
80 ```php | |
81 <?php | |
82 | |
83 use PhpParser\{ConstExprEvaluator, ConstExprEvaluationException}; | |
84 use PhpParser\Node\Expr; | |
85 | |
86 $evalutator = new ConstExprEvaluator(function(Expr $expr) { | |
87 if ($expr instanceof Expr\ConstFetch) { | |
88 return fetchConstantSomehow($expr); | |
89 } | |
90 if ($expr instanceof Expr\ClassConstFetch) { | |
91 return fetchClassConstantSomehow($expr); | |
92 } | |
93 // etc. | |
94 throw new ConstExprEvaluationException( | |
95 "Expression of type {$expr->getType()} cannot be evaluated"); | |
96 }); | |
97 | |
98 try { | |
99 $evalutator->evaluateSilently($someExpr); | |
100 } catch (ConstExprEvaluationException $e) { | |
101 // Handle exception | |
102 } | |
103 ``` | |
104 | |
105 Implementers are advised to ensure that evaluation of indirect constant references cannot lead to | |
106 infinite recursion. For example, the following code could lead to infinite recursion if constant | |
107 lookup is implemented naively. | |
108 | |
109 ```php | |
110 <?php | |
111 class Test { | |
112 const A = self::B; | |
113 const B = self::A; | |
114 } | |
115 ``` |