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 declare(strict_types=1); |
||
2 | |||
3 | /* |
||
4 | * This file is part of the pinepain/js-sandbox PHP library. |
||
5 | * |
||
6 | * Copyright (c) 2016-2017 Bogdan Padalko <[email protected]> |
||
7 | * |
||
8 | * Licensed under the MIT license: http://opensource.org/licenses/MIT |
||
9 | * |
||
10 | * For the full copyright and license information, please view the |
||
11 | * LICENSE file that was distributed with this source or visit |
||
12 | * http://opensource.org/licenses/MIT |
||
13 | */ |
||
14 | |||
15 | |||
16 | namespace Pinepain\JsSandbox\Specs\Builder; |
||
17 | |||
18 | |||
19 | use Pinepain\JsSandbox\Decorators\DecoratorSpecBuilderInterface; |
||
20 | use Pinepain\JsSandbox\Specs\Builder\Exceptions\FunctionSpecBuilderException; |
||
21 | use Pinepain\JsSandbox\Specs\FunctionSpec; |
||
22 | use Pinepain\JsSandbox\Specs\FunctionSpecInterface; |
||
23 | use Pinepain\JsSandbox\Specs\ParametersList; |
||
24 | use Pinepain\JsSandbox\Specs\ParametersListInterface; |
||
25 | use Pinepain\JsSandbox\Specs\ReturnSpec\AnyReturnSpec; |
||
26 | use Pinepain\JsSandbox\Specs\ReturnSpec\ReturnSpecInterface; |
||
27 | use Pinepain\JsSandbox\Specs\ReturnSpec\VoidReturnSpec; |
||
28 | use Pinepain\JsSandbox\Specs\ThrowSpec\EchoThrowSpec; |
||
29 | use Pinepain\JsSandbox\Specs\ThrowSpec\ThrowSpecList; |
||
30 | use Pinepain\JsSandbox\Specs\ThrowSpec\ThrowSpecListInterface; |
||
31 | |||
32 | |||
33 | class FunctionSpecBuilder implements FunctionSpecBuilderInterface |
||
34 | { |
||
35 | /** |
||
36 | * @var DecoratorSpecBuilderInterface |
||
37 | */ |
||
38 | private $decorator; |
||
39 | |||
40 | /** |
||
41 | * @var ParameterSpecBuilderInterface |
||
42 | */ |
||
43 | private $builder; |
||
44 | /** |
||
45 | * @var array |
||
46 | */ |
||
47 | private $return_types; |
||
48 | 11 | /** |
|
49 | * @var string |
||
50 | 11 | */ |
|
51 | private $default_return_type = 'any'; |
||
52 | 11 | ||
53 | 11 | private $regexp = '/ |
|
54 | 11 | ^ |
|
55 | \s* |
||
56 | 11 | (?<decorators> |
|
57 | \s* |
||
58 | (?:\@[\w-]+(?:\s*\([^\)]*\)\s*)?\s*)+ |
||
59 | \s* |
||
60 | )? |
||
61 | 11 | \( |
|
62 | \s* |
||
63 | 11 | (?<params>([^,]+)(?:\s*,\s*[^,]+)*)? |
|
64 | \s* |
||
65 | 11 | \) |
|
66 | 1 | (?: |
|
67 | \s* |
||
68 | \: |
||
69 | 10 | \s* |
|
70 | (?<return>\w+\b)? |
||
71 | 9 | \s* |
|
72 | )? |
||
73 | 9 | (?: |
|
74 | 9 | \s* |
|
75 | 8 | throws |
|
76 | \s* |
||
77 | 8 | (?<throws>(\\\\?[a-z][\w\\\\]+)(?:\s*\,\s*(?-1))*)? |
|
78 | \s* |
||
79 | )? |
||
80 | 1 | \s* |
|
81 | $ |
||
82 | /xi'; |
||
83 | 9 | ||
84 | private $decorators_regexp = '/([^\@"\']+)|("([^"]*)")|(\'([^\']*)\')/i'; |
||
85 | 9 | ||
86 | 1 | public function __construct(DecoratorSpecBuilderInterface $decorator, ParameterSpecBuilderInterface $builder) |
|
87 | { |
||
88 | $this->decorator = $decorator; |
||
89 | 8 | $this->builder = $builder; |
|
90 | |||
91 | $this->return_types = [ |
||
92 | 9 | 'any' => new AnyReturnSpec(), |
|
93 | 'void' => new VoidReturnSpec(), |
||
94 | 9 | ]; |
|
95 | } |
||
96 | 9 | ||
97 | 1 | /** |
|
98 | 1 | * {@inheritdoc} |
|
99 | 1 | */ |
|
100 | public function build(string $definition): FunctionSpecInterface |
||
101 | { |
||
102 | $definition = trim($definition); |
||
103 | 9 | ||
104 | if (!$definition) { |
||
105 | throw new FunctionSpecBuilderException('Definition must be non-empty string'); |
||
106 | 8 | } |
|
107 | |||
108 | 8 | if (preg_match($this->regexp, $definition, $matches)) { |
|
109 | |||
110 | 8 | $decorators = $this->getDecoratorsList($matches['decorators'] ?? ''); |
|
111 | 1 | $params = $this->getParametersList($matches['params'] ?? ''); |
|
112 | $return = $this->getReturnType(($matches['return'] ?? '') ?: $this->default_return_type); |
||
113 | 1 | $throws = $this->getThrowsList($matches['throws'] ?? ''); |
|
114 | 1 | ||
115 | return new FunctionSpec($params, $throws, $return, $decorators); |
||
116 | } |
||
117 | |||
118 | 8 | throw new FunctionSpecBuilderException("Unable to parse definition: '{$definition}'"); |
|
119 | } |
||
120 | |||
121 | protected function getReturnType(string $definition): ReturnSpecInterface |
||
122 | { |
||
123 | if (!isset($this->return_types[$definition])) { |
||
124 | throw new FunctionSpecBuilderException("Invalid return type: '{$definition}'"); |
||
125 | } |
||
126 | |||
127 | return $this->return_types[$definition]; |
||
128 | } |
||
129 | |||
130 | protected function getParametersList(string $definition): ParametersListInterface |
||
131 | { |
||
132 | $params = []; |
||
133 | |||
134 | if ($definition) { |
||
135 | $raw_params_definition = explode(',', $definition); |
||
136 | foreach ($raw_params_definition as $param_definition) { |
||
137 | $params[] = $this->builder->build(trim($param_definition)); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | return new ParametersList(...$params); |
||
142 | } |
||
143 | |||
144 | protected function getThrowsList(string $definition): ThrowSpecListInterface |
||
145 | { |
||
146 | $specs = []; |
||
147 | |||
148 | if ($definition) { |
||
149 | $classes = array_filter(array_map('\trim', explode(', ', $definition))); |
||
150 | |||
151 | foreach ($classes as $class) { |
||
152 | $specs[] = new EchoThrowSpec($class); |
||
153 | } |
||
154 | } |
||
155 | |||
156 | return new ThrowSpecList(...$specs); |
||
157 | } |
||
158 | |||
159 | protected function getDecoratorsList(string $definition): array |
||
160 | { |
||
161 | $definition = trim($definition); |
||
162 | |||
163 | if (!$definition) { |
||
164 | return []; |
||
165 | } |
||
166 | |||
167 | $separators = preg_split($this->decorators_regexp, $definition, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_OFFSET_CAPTURE); |
||
168 | |||
169 | if (!$separators) { |
||
0 ignored issues
–
show
|
|||
170 | // UNEXPECTED |
||
171 | throw new FunctionSpecBuilderException("Invalid decorators: '{$definition}'"); |
||
172 | } |
||
173 | |||
174 | $decorators = []; |
||
175 | |||
176 | $sequences = array_column($separators, 1); |
||
177 | |||
178 | $sequences[] = strlen($definition); |
||
179 | |||
180 | while (count($sequences) > 1) { |
||
181 | $start = array_shift($sequences); |
||
182 | $end = $sequences[0]; |
||
183 | |||
184 | $part = trim(substr($definition, $start, $end - $start)); |
||
185 | |||
186 | $decorators[] = $this->decorator->build($part); |
||
187 | } |
||
188 | |||
189 | return $decorators; |
||
190 | } |
||
191 | } |
||
192 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.