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 ILess |
||
5 | * |
||
6 | * For the full copyright and license information, please view the LICENSE |
||
7 | * file that was distributed with this source code. |
||
8 | */ |
||
9 | |||
10 | namespace ILess\Exception; |
||
11 | |||
12 | use ILess\FileInfo; |
||
13 | use ILess\Util; |
||
14 | use ILess\ImportedFile; |
||
15 | |||
16 | /** |
||
17 | * Base exception. |
||
18 | */ |
||
19 | class Exception extends \Exception |
||
20 | { |
||
21 | /** |
||
22 | * The current file. |
||
23 | * |
||
24 | * @var ImportedFile|FileInfo|string |
||
25 | */ |
||
26 | private $currentFile; |
||
27 | |||
28 | /** |
||
29 | * The current parser index. |
||
30 | * |
||
31 | * @var int |
||
32 | */ |
||
33 | private $index; |
||
34 | |||
35 | /** |
||
36 | * Current line. |
||
37 | * |
||
38 | * @var int|null |
||
39 | */ |
||
40 | private $errorLine; |
||
41 | |||
42 | /** |
||
43 | * Current column. |
||
44 | * |
||
45 | * @var int|null |
||
46 | */ |
||
47 | private $errorColumn; |
||
48 | |||
49 | /** |
||
50 | * Excerpt from the string which contains error. |
||
51 | * |
||
52 | * @var Util\StringExcerpt |
||
53 | */ |
||
54 | private $excerpt; |
||
55 | |||
56 | /** |
||
57 | * File editor link. Allows variable holders:. |
||
58 | * |
||
59 | * * `%file` or `%f` - current file |
||
60 | * * `%line` or `%l` - current line |
||
61 | * |
||
62 | * @var string |
||
63 | */ |
||
64 | protected static $fileEditUrlFormat = 'editor://open?file=%f&line=%l'; |
||
65 | |||
66 | /** |
||
67 | * File excerpt line number. |
||
68 | * |
||
69 | * @var int|false |
||
70 | */ |
||
71 | protected static $fileExcerptLineNumber = 3; |
||
72 | |||
73 | /** |
||
74 | * Constructor. |
||
75 | * |
||
76 | * @param string $message The exception message |
||
77 | * @param int $index The current parser index |
||
78 | * @param FileInfo|ImportedFile|string $currentFile The file |
||
79 | * @param \Exception $previous Previous exception |
||
80 | * @param int $code The exception code |
||
81 | */ |
||
82 | public function __construct( |
||
83 | $message = null, |
||
84 | $index = null, |
||
85 | $currentFile = null, |
||
86 | \Exception $previous = null, |
||
87 | $code = 0 |
||
88 | ) { |
||
89 | $message = $this->formatMessage($message, $previous); |
||
90 | |||
91 | parent::__construct($message, $code, $previous); |
||
92 | |||
93 | $this->currentFile = $currentFile; |
||
94 | $this->index = $index; |
||
95 | |||
96 | if ($currentFile && $this->index !== null) { |
||
97 | $this->updateFileErrorInformation(); |
||
98 | } |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Formats the message. |
||
103 | * |
||
104 | * @param string $message The exception message |
||
105 | * @param \Exception $previous Previous exception |
||
106 | * |
||
107 | * @return string |
||
108 | */ |
||
109 | private function formatMessage($message, \Exception $previous = null) |
||
110 | { |
||
111 | $messageFormatted = $message; |
||
112 | if ($previous && $previous->getMessage() !== $message) { |
||
113 | $messageFormatted .= ': ' . $previous->getMessage(); |
||
114 | } |
||
115 | |||
116 | return $messageFormatted; |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Returns the current line and column. |
||
121 | * |
||
122 | * @param FileInfo|ImportedFile|string $currentFile The file |
||
123 | * @param int $index Current position index |
||
124 | * @param bool $excerpt Include the string excerpt? |
||
125 | * |
||
126 | * @return array |
||
127 | */ |
||
128 | protected function getLocation($currentFile, $index, $column = null, $excerpt = true) |
||
129 | { |
||
130 | $line = $col = $excerptContent = null; |
||
131 | if ($index !== null && $currentFile) { |
||
132 | $content = null; |
||
133 | if ($currentFile instanceof FileInfo |
||
134 | && $currentFile->importedFile |
||
135 | ) { |
||
136 | $content = $currentFile->importedFile->getContent(); |
||
137 | } elseif (is_string($currentFile) && Util::isPathAbsolute($currentFile) |
||
138 | && is_readable($currentFile) |
||
139 | ) { |
||
140 | $content = file_get_contents($currentFile); |
||
141 | } |
||
142 | if ($content) { |
||
143 | list($line, $col, $excerptContent) = Util::getLocation($content, $index, $column, $excerpt); |
||
144 | } |
||
145 | } |
||
146 | |||
147 | return [ |
||
148 | $line, |
||
149 | $col, |
||
150 | $excerptContent, |
||
151 | ]; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Updates the line, column and excerpt. |
||
156 | */ |
||
157 | protected function updateFileErrorInformation() |
||
158 | { |
||
159 | // recalculate the location |
||
160 | list($this->errorLine, $this->errorColumn, $this->excerpt) = |
||
161 | $this->getLocation($this->currentFile, $this->index, $this->errorColumn, self::getFileExcerptLineNumber()); |
||
0 ignored issues
–
show
|
|||
162 | } |
||
163 | |||
164 | /** |
||
165 | * Sets the editor url format. |
||
166 | * |
||
167 | * @param string $format |
||
168 | */ |
||
169 | public static function setFileEditorUrlFormat($format) |
||
170 | { |
||
171 | self::$fileEditUrlFormat = (string) $format; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Returns the editor url format. |
||
176 | * |
||
177 | * @return string |
||
178 | */ |
||
179 | public static function getFileEditorUrlFormat() |
||
180 | { |
||
181 | return self::$fileEditUrlFormat; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Sets the number of lines to display in file excerpts when an exception is displayed. |
||
186 | * |
||
187 | * @param int|false $number |
||
188 | */ |
||
189 | public static function setFileExcerptLineNumber($number) |
||
190 | { |
||
191 | self::$fileExcerptLineNumber = $number; |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Returns the number of lines to display in file excerpts. |
||
196 | * |
||
197 | * @return int|false |
||
198 | */ |
||
199 | public static function getFileExcerptLineNumber() |
||
200 | { |
||
201 | return self::$fileExcerptLineNumber; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * Returns the file. |
||
206 | * |
||
207 | * @return ImportedFile|FileInfo|null |
||
208 | */ |
||
209 | public function getCurrentFile() |
||
210 | { |
||
211 | return $this->currentFile; |
||
212 | } |
||
213 | |||
214 | /** |
||
215 | * Sets the current file. |
||
216 | * |
||
217 | * @param ImportedFile|FileInfo|string $file |
||
218 | * @param int $index The current index |
||
219 | */ |
||
220 | public function setCurrentFile($file, $index = null) |
||
221 | { |
||
222 | $this->currentFile = $file; |
||
223 | if ($index !== null) { |
||
224 | $this->index = $index; |
||
225 | } |
||
226 | $this->updateFileErrorInformation(); |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Returns the current index. |
||
231 | * |
||
232 | * @return int |
||
233 | */ |
||
234 | final public function getIndex() |
||
235 | { |
||
236 | return $this->index; |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Returns the excerpt from the string which contains the error. |
||
241 | * |
||
242 | * @return Util\StringExcerpt|null |
||
243 | */ |
||
244 | final public function getExcerpt() |
||
245 | { |
||
246 | return $this->excerpt; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Sets index. |
||
251 | * |
||
252 | * @param int $index |
||
253 | */ |
||
254 | final public function setIndex($index) |
||
255 | { |
||
256 | $this->index = $index; |
||
257 | $this->updateFileErrorInformation(); |
||
258 | } |
||
259 | |||
260 | /** |
||
261 | * Returns current line from the file. |
||
262 | * |
||
263 | * @return int|null |
||
264 | */ |
||
265 | final public function getErrorLine() |
||
266 | { |
||
267 | return $this->errorLine; |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * Returns the error column. |
||
272 | * |
||
273 | * @return int|null |
||
274 | */ |
||
275 | final public function getErrorColumn() |
||
276 | { |
||
277 | return $this->errorColumn; |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * Returns file editor link. The link format can be customized. |
||
282 | * |
||
283 | * @param FileInfo|string $file The current file |
||
284 | * @param int $line |
||
285 | * |
||
286 | * @return string|void |
||
287 | * |
||
288 | * @see setFileEditorUrlFormat |
||
289 | */ |
||
290 | protected function getFileEditorLink($file, $line = null) |
||
291 | { |
||
292 | if ($file instanceof FileInfo) { |
||
293 | $path = $file->filename; |
||
294 | if ($file->importedFile) { |
||
295 | $path = $file->importedFile->getPath(); |
||
296 | } |
||
297 | if (strpos($path, '__string_to_parse__') === 0) { |
||
298 | $path = '[input string]'; |
||
299 | } |
||
300 | } else { |
||
301 | $path = $file; |
||
302 | } |
||
303 | |||
304 | // when in cli or not accessible via filesystem, don't generate links |
||
305 | if (PHP_SAPI == 'cli' || !Util::isPathAbsolute($path)) { |
||
306 | return $path; |
||
307 | } |
||
308 | |||
309 | return sprintf('<a href="%s" class="file-edit">%s</a>', htmlspecialchars(strtr(self::$fileEditUrlFormat, [ |
||
310 | // allow more formats |
||
311 | '%f' => $path, |
||
312 | '%file' => $path, |
||
313 | '%line' => $line, |
||
314 | '%l' => $line, |
||
315 | ])), $path); |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * Converts the exception to string. |
||
320 | * |
||
321 | * @return string |
||
322 | */ |
||
323 | public function __toString() |
||
324 | { |
||
325 | return $this->toString(true, php_sapi_name() !== 'cli'); |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * Converts the exception to string. |
||
330 | * |
||
331 | * @param bool $includeExcerpt Include excerpt? |
||
332 | * @param bool $html Convert to HTML? |
||
333 | * |
||
334 | * @return string |
||
335 | */ |
||
336 | public function toString($includeExcerpt = true, $html = true) |
||
337 | { |
||
338 | $string = []; |
||
339 | if ($this->currentFile) { |
||
340 | // we have an line from the file |
||
341 | if (($line = $this->getErrorLine()) !== null) { |
||
342 | $string[] = sprintf('%s in %s on line: %s, column: %s', $this->message, |
||
343 | $this->getFileEditorLink($this->currentFile, $line), $line, $this->errorColumn); |
||
0 ignored issues
–
show
It seems like
$this->currentFile can also be of type object<ILess\ImportedFile> ; however, ILess\Exception\Exception::getFileEditorLink() does only seem to accept object<ILess\FileInfo>|string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
344 | if ($includeExcerpt && $this->excerpt) { |
||
345 | if ($html) { |
||
346 | $string[] = sprintf('<pre>%s</pre>', $this->excerpt->toHtml()); |
||
347 | } else { |
||
348 | $string[] = $this->excerpt->toText(); |
||
349 | } |
||
350 | } |
||
351 | } else { |
||
352 | $string[] = sprintf('%s in %s on line: ?', $this->message, |
||
353 | $this->getFileEditorLink($this->currentFile)); |
||
0 ignored issues
–
show
It seems like
$this->currentFile can also be of type object<ILess\ImportedFile> ; however, ILess\Exception\Exception::getFileEditorLink() does only seem to accept object<ILess\FileInfo>|string , maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. ![]() |
|||
354 | } |
||
355 | } else { |
||
356 | $string[] = $this->message; |
||
357 | } |
||
358 | |||
359 | return implode("\n", $string); |
||
360 | } |
||
361 | |||
362 | /** |
||
363 | * @return string |
||
364 | */ |
||
365 | public function prettyPrint($trace = false) |
||
366 | { |
||
367 | $error = sprintf('<h2>%s</h2>%s', get_class($this), $this->__toString()); |
||
368 | if ($trace) { |
||
369 | $error .= sprintf('<h3>Trace</h3><pre class="exception-trace">%s</pre>', $this->getTraceAsString()); |
||
370 | } |
||
371 | |||
372 | if ($previous = $this->getPrevious()) { |
||
373 | $error .= '<h3>Caused by: ' . get_class($previous) . '</h3>'; |
||
374 | $error .= $previous->getMessage(); |
||
375 | $error .= '<pre class="exception-trace">' . $previous->getTraceAsString() . '</pre>'; |
||
376 | } |
||
377 | |||
378 | return $error; |
||
379 | } |
||
380 | } |
||
381 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.