This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the fubhy/math-php package. |
||
5 | * |
||
6 | * (c) Sebastian Siemssen <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace Fubhy\Math; |
||
13 | |||
14 | use Fubhy\Math\Exception\IncorrectExpressionException; |
||
15 | use Fubhy\Math\Exception\UnknownVariableException; |
||
16 | use Fubhy\Math\Token\FunctionToken; |
||
17 | use Fubhy\Math\Token\NumberToken; |
||
18 | use Fubhy\Math\Token\Operator\OperatorTokenInterface; |
||
19 | use Fubhy\Math\Token\VariableToken; |
||
20 | use Moontoast\Math\BigNumber; |
||
21 | |||
22 | /** |
||
23 | * Parser for mathematical expressions. |
||
24 | * |
||
25 | * @author Sebastian Siemssen <[email protected]> |
||
26 | */ |
||
27 | class Calculator |
||
28 | { |
||
29 | /** |
||
30 | * Static cache of token streams in reverse polish (postfix) notation. |
||
31 | * |
||
32 | * @var array |
||
33 | */ |
||
34 | protected $tokenCache = []; |
||
35 | |||
36 | /** |
||
37 | * Optional VariableResolverInterface to resolve variables value at runtime |
||
38 | * |
||
39 | * @var VariableResolverInterface |
||
40 | */ |
||
41 | protected $variableResolver; |
||
42 | |||
43 | /** |
||
44 | * Constructs a new Calculator object. |
||
45 | * |
||
46 | * @param array $constants |
||
47 | * @param array $functions |
||
48 | * @param array $operators |
||
49 | */ |
||
50 | public function __construct(array $constants = null, array $functions = null, array $operators = null) |
||
51 | { |
||
52 | $this->lexer = new Lexer(); |
||
0 ignored issues
–
show
|
|||
53 | |||
54 | $constants = $constants ?: static::getDefaultConstants(); |
||
55 | $functions = $functions ?: static::getDefaultFunctions(); |
||
56 | $operators = $operators ?: static::getDefaultOperators(); |
||
57 | |||
58 | foreach ($constants as $constant) { |
||
59 | $this->lexer->addConstant($constant[0], $constant[1]); |
||
60 | } |
||
61 | |||
62 | foreach ($functions as $function) { |
||
63 | $this->lexer->addFunction($function[0], $function[1], $function[2]); |
||
64 | } |
||
65 | |||
66 | foreach ($operators as $operator) { |
||
67 | $this->lexer->addOperator($operator[0], $operator[1]); |
||
68 | } |
||
69 | |||
70 | } |
||
71 | |||
72 | /** |
||
73 | * Calculates the result of a mathematical expression. |
||
74 | * |
||
75 | * @param string $expression |
||
76 | * The mathematical expression. |
||
77 | * @param array $variables |
||
78 | * A list of numerical values keyed by their variable names. |
||
79 | * |
||
80 | * @return mixed |
||
81 | * The result of the mathematical expression. |
||
82 | * |
||
83 | * @throws \Fubhy\Math\Exception\IncorrectExpressionException |
||
84 | * @throws \Fubhy\Math\Exception\UnknownVariableException |
||
85 | */ |
||
86 | public function calculate($expression, $variables = array()) |
||
87 | { |
||
88 | $hash = md5($expression); |
||
89 | if (!isset($this->tokenCache[$hash])) { |
||
90 | $this->tokenCache[$hash] = $this->lexer->postfix($this->lexer->tokenize($expression)); |
||
91 | } |
||
92 | |||
93 | $stack = []; |
||
94 | $tokens = $this->tokenCache[$hash]; |
||
95 | foreach ($tokens as $token) { |
||
96 | if ($token instanceof NumberToken) { |
||
97 | array_push($stack, $token); |
||
98 | } elseif ($token instanceof VariableToken) { |
||
99 | $identifier = $token->getValue(); |
||
100 | |||
101 | if (!isset($variables[$identifier]) && $this->variableResolver) { |
||
102 | $variableValue = $this->variableResolver->resolveVariable($identifier); |
||
103 | if ($variableValue !== null) { |
||
104 | $variables[$identifier] = $variableValue; |
||
105 | } |
||
106 | } |
||
107 | |||
108 | if (!isset($variables[$identifier])) { |
||
109 | throw new UnknownVariableException( |
||
110 | 'Could not find value for variable '.$identifier.' at offset '.$token->getOffset() |
||
111 | ); |
||
112 | } |
||
113 | |||
114 | array_push($stack, new NumberToken($token->getOffset(), $variables[$identifier])); |
||
115 | } elseif ($token instanceof OperatorTokenInterface || $token instanceof FunctionToken) { |
||
116 | array_push($stack, $token->execute($stack)); |
||
117 | } |
||
118 | } |
||
119 | |||
120 | $result = array_pop($stack); |
||
121 | if (!empty($stack)) { |
||
122 | throw new IncorrectExpressionException(); |
||
123 | } |
||
124 | |||
125 | return $result->getValue(); |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * Returns the default list of operators. |
||
130 | * |
||
131 | * @return array |
||
132 | * The default list of operators. |
||
133 | */ |
||
134 | public static function getDefaultOperators() |
||
135 | { |
||
136 | return [ |
||
137 | ['plus', 'Fubhy\Math\Token\Operator\PlusToken'], |
||
138 | ['minus', 'Fubhy\Math\Token\Operator\MinusToken'], |
||
139 | ['multiply', 'Fubhy\Math\Token\Operator\MultiplyToken'], |
||
140 | ['division', 'Fubhy\Math\Token\Operator\DivisionToken'], |
||
141 | ['modulus', 'Fubhy\Math\Token\Operator\ModulusToken'], |
||
142 | ['power', 'Fubhy\Math\Token\Operator\PowerToken'], |
||
143 | ]; |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Returns the default list of functions. |
||
148 | * |
||
149 | * @return array |
||
150 | * The default list of functions. |
||
151 | */ |
||
152 | public static function getDefaultFunctions() |
||
153 | { |
||
154 | return [ |
||
155 | [ |
||
156 | 'abs', |
||
157 | function ($number) { |
||
158 | return (new BigNumber($number)) |
||
159 | ->abs() |
||
160 | ->getValue(); |
||
161 | }, |
||
162 | 1, |
||
163 | ], |
||
164 | [ |
||
165 | 'ceil', |
||
166 | function ($number) { |
||
167 | return (new BigNumber($number)) |
||
168 | ->ceil() |
||
169 | ->getValue(); |
||
170 | }, |
||
171 | 1, |
||
172 | ], |
||
173 | [ |
||
174 | 'floor', |
||
175 | function ($number) { |
||
176 | return (new BigNumber($number)) |
||
177 | ->floor() |
||
178 | ->getValue(); |
||
179 | }, |
||
180 | 1, |
||
181 | ], |
||
182 | [ |
||
183 | 'powmod', |
||
184 | function ($number, $pow, $mod) { |
||
185 | return (new BigNumber($number)) |
||
186 | ->powMod($pow, $mod) |
||
187 | ->getValue(); |
||
188 | }, |
||
189 | 3, |
||
190 | ], |
||
191 | [ |
||
192 | 'round', |
||
193 | function ($number) { |
||
194 | return (new BigNumber($number)) |
||
195 | ->round() |
||
196 | ->getValue(); |
||
197 | }, |
||
198 | 1, |
||
199 | ], |
||
200 | [ |
||
201 | 'signum', |
||
202 | function ($number) { |
||
203 | return (new BigNumber($number)) |
||
204 | ->signum(); |
||
205 | }, |
||
206 | 1, |
||
207 | ], |
||
208 | [ |
||
209 | 'sqrt', |
||
210 | function ($number) { |
||
211 | return (new BigNumber($number)) |
||
212 | ->sqrt() |
||
213 | ->getValue(); |
||
214 | }, |
||
215 | 1, |
||
216 | ], |
||
217 | ]; |
||
218 | } |
||
219 | |||
220 | /** |
||
221 | * Returns the default list of constants. |
||
222 | * |
||
223 | * @return array |
||
224 | * The default list of constants. |
||
225 | */ |
||
226 | public static function getDefaultConstants() |
||
227 | { |
||
228 | return [ |
||
229 | ['pi', pi()], |
||
230 | ['e', exp(1)], |
||
231 | ]; |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * @param VariableResolverInterface $variableResolver |
||
236 | */ |
||
237 | public function setVariableResolver($variableResolver) |
||
238 | { |
||
239 | $this->variableResolver = $variableResolver; |
||
240 | } |
||
241 | |||
242 | } |
||
243 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: