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 namespace Understand\UnderstandLaravel5; |
||
2 | |||
3 | use Exception; |
||
4 | use Throwable; |
||
5 | use InvalidArgumentException; |
||
6 | use SplFileObject; |
||
7 | |||
8 | class ExceptionEncoder |
||
9 | { |
||
10 | |||
11 | /** |
||
12 | * @var string |
||
13 | */ |
||
14 | protected $projectRoot; |
||
15 | |||
16 | /** |
||
17 | * @var int |
||
18 | */ |
||
19 | protected $stackTraceLimit = 100; |
||
20 | |||
21 | /** |
||
22 | * @param integer $limit |
||
23 | */ |
||
24 | public function setStackTraceLimit($limit) |
||
25 | { |
||
26 | $this->stackTraceLimit = $limit; |
||
27 | } |
||
28 | |||
29 | /** |
||
30 | * @param string $projectRoot |
||
31 | */ |
||
32 | public function setProjectRoot($projectRoot) |
||
33 | { |
||
34 | $this->projectRoot = $projectRoot; |
||
35 | } |
||
36 | |||
37 | /** |
||
38 | * Serialize exception object |
||
39 | * |
||
40 | * @param mixed $exception |
||
41 | * @return array |
||
42 | */ |
||
43 | public function exceptionToArray($exception) |
||
44 | { |
||
45 | if ( ! ($exception instanceof Exception || $exception instanceof Throwable)) |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
46 | { |
||
47 | throw new InvalidArgumentException('$exception must be instance of Exception or Throwable'); |
||
48 | } |
||
49 | |||
50 | $trace = $exception->getTrace(); |
||
51 | $className = get_class($exception); |
||
52 | $message = $exception->getMessage() ? $exception->getMessage() : $className; |
||
53 | |||
54 | return [ |
||
55 | 'message' => $message, |
||
56 | 'class' => $className, |
||
57 | 'code' => $exception->getCode(), |
||
58 | 'file' => $this->removeProjectRoot($exception->getFile()), |
||
59 | 'line' => $exception->getLine(), |
||
60 | 'stack' => $this->stackTraceToArray($trace, $exception->getFile(), $exception->getLine()) |
||
61 | ]; |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * @param array $errorLog |
||
66 | * @return array |
||
67 | */ |
||
68 | public function setCurrentStackTrace(array $errorLog) |
||
69 | { |
||
70 | $level = isset($errorLog['level']) ? $errorLog['level'] : null; |
||
71 | $stackTrace = $this->getCurrentStackTrace($level); |
||
0 ignored issues
–
show
The call to
ExceptionEncoder::getCurrentStackTrace() has too many arguments starting with $level .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
72 | $firstLineSet = false; |
||
73 | |||
74 | foreach($stackTrace as $trace) |
||
75 | { |
||
76 | if ($firstLineSet) |
||
77 | { |
||
78 | break; |
||
79 | } |
||
80 | |||
81 | $firstLineSet = true; |
||
82 | |||
83 | $errorLog['class'] = null; |
||
84 | $errorLog['file'] = isset($trace['file']) ? $trace['file'] : null; |
||
85 | $errorLog['line'] = isset($trace['line']) ? $trace['line'] : null; |
||
86 | } |
||
87 | |||
88 | $errorLog['stack'] = $stackTrace; |
||
89 | |||
90 | return $errorLog; |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * @return array |
||
95 | */ |
||
96 | protected function getCurrentStackTrace() |
||
97 | { |
||
98 | $stackTrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, $this->stackTraceLimit); |
||
99 | $vendorExcluded = false; |
||
100 | |||
101 | foreach($stackTrace as $index => $trace) |
||
102 | { |
||
103 | // exclude Understand service provider and helper classes |
||
104 | if (isset($trace['class']) && strpos($trace['class'], 'Understand\UnderstandLaravel5\\') === 0) |
||
105 | { |
||
106 | unset($stackTrace[$index]); |
||
107 | } |
||
108 | |||
109 | if ( ! isset($trace['file'])) |
||
110 | { |
||
111 | $vendorExcluded = true; |
||
112 | } |
||
113 | |||
114 | if ($vendorExcluded) |
||
115 | { |
||
116 | continue; |
||
117 | } |
||
118 | |||
119 | // exclude `vendor` folder until project path reached |
||
120 | if (strpos($trace['file'], $this->projectRoot . 'vendor' . DIRECTORY_SEPARATOR) === 0) |
||
121 | { |
||
122 | unset($stackTrace[$index]); |
||
123 | } |
||
124 | else |
||
125 | { |
||
126 | $vendorExcluded = true; |
||
127 | } |
||
128 | } |
||
129 | |||
130 | return $this->stackTraceToArray($stackTrace); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * Serialize stack trace to array |
||
135 | * |
||
136 | * @param array $stackTrace |
||
137 | * @return array |
||
138 | */ |
||
139 | public function stackTraceToArray(array $stackTrace, $topFile = null, $topLine = null) |
||
140 | { |
||
141 | $stack = []; |
||
142 | $counter = 0; |
||
143 | |||
144 | foreach ($stackTrace as $trace) |
||
145 | { |
||
146 | // Exception object `getTrace` does not return file and line number for the first line |
||
147 | // http://php.net/manual/en/exception.gettrace.php#107563 |
||
148 | if (isset($topFile, $topLine) && $topFile && $topLine) |
||
149 | { |
||
150 | $trace['file'] = $topFile; |
||
151 | $trace['line'] = $topLine; |
||
152 | |||
153 | unset($topFile, $topLine); |
||
154 | } |
||
155 | |||
156 | $type = $this->stackTraceCallToString($trace); |
||
157 | $args = $this->stackTraceArgsToArray($trace); |
||
158 | |||
159 | $stack[] = [ |
||
160 | 'class' => isset($trace['class']) ? $trace['class'] : null, |
||
161 | 'function' => isset($trace['function']) ? $trace['function'] : null, |
||
162 | 'args' => $args, |
||
163 | 'type' => $type, |
||
164 | 'file' => $this->getStackTraceFile($trace), |
||
165 | 'line' => $this->getStackTraceLine($trace), |
||
166 | 'code' => $this->getCode($this->getStackTraceFile($trace), $this->getStackTraceLine($trace)), |
||
167 | ]; |
||
168 | |||
169 | $counter++; |
||
170 | |||
171 | if ($counter >= $this->stackTraceLimit) |
||
172 | { |
||
173 | break; |
||
174 | } |
||
175 | } |
||
176 | |||
177 | return $stack; |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * @param $relativePath |
||
182 | * @param $line |
||
183 | * @param int $linesAround |
||
184 | * @return array|void |
||
185 | */ |
||
186 | public function getCode($relativePath, $line, $linesAround = 6) |
||
187 | { |
||
188 | if ( ! $relativePath || ! $line) |
||
189 | { |
||
190 | return; |
||
191 | } |
||
192 | |||
193 | $filePath = $this->projectRoot . $relativePath; |
||
194 | |||
195 | try |
||
196 | { |
||
197 | $file = new SplFileObject($filePath); |
||
198 | $file->setMaxLineLen(250); |
||
199 | $file->seek(PHP_INT_MAX); |
||
200 | $codeLines = []; |
||
201 | |||
202 | $from = max(0, $line - $linesAround - 2); |
||
203 | $to = min($line + $linesAround -1, $file->key() + 1); |
||
204 | |||
205 | $file->seek($from); |
||
206 | |||
207 | while ($file->key() < $to && ! $file->eof()) |
||
208 | { |
||
209 | $file->next(); |
||
210 | // `key()` returns 0 as the first line |
||
211 | $codeLines[] = [ |
||
212 | 'line' => $file->key() + 1, |
||
213 | 'code' => rtrim($file->current()) |
||
214 | ]; |
||
215 | } |
||
216 | |||
217 | return $codeLines; |
||
218 | } |
||
219 | catch (\Throwable $e) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
220 | {} |
||
221 | catch (\Exception $e) |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
|
|||
222 | {} |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Return stack trace line number |
||
227 | * |
||
228 | * @param array $trace |
||
229 | * @return mixed |
||
230 | */ |
||
231 | protected function getStackTraceLine(array $trace) |
||
232 | { |
||
233 | if (isset($trace['line'])) |
||
234 | { |
||
235 | return $trace['line']; |
||
236 | } |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * Return stack trace file |
||
241 | * |
||
242 | * @param array $trace |
||
243 | * @return mixed |
||
244 | */ |
||
245 | protected function getStackTraceFile(array $trace) |
||
246 | { |
||
247 | if (isset($trace['file'])) |
||
248 | { |
||
249 | return $this->removeProjectRoot($trace['file']); |
||
250 | } |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Return call type |
||
255 | * |
||
256 | * @param array $trace |
||
257 | * @return string |
||
258 | */ |
||
259 | protected function stackTraceCallToString(array $trace) |
||
260 | { |
||
261 | if (! isset($trace['type'])) |
||
262 | { |
||
263 | return 'function'; |
||
264 | } |
||
265 | |||
266 | if ($trace['type'] == '::') |
||
267 | { |
||
268 | return 'static'; |
||
269 | } |
||
270 | |||
271 | if ($trace['type'] == '->') |
||
272 | { |
||
273 | return 'method'; |
||
274 | } |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Serialize stack trace function arguments |
||
279 | * |
||
280 | * @param array $trace |
||
281 | * @return array |
||
282 | */ |
||
283 | protected function stackTraceArgsToArray(array $trace) |
||
284 | { |
||
285 | $params = []; |
||
286 | |||
287 | if (! isset($trace['args'])) |
||
288 | { |
||
289 | return $params; |
||
290 | } |
||
291 | |||
292 | foreach ($trace['args'] as $arg) |
||
293 | { |
||
294 | if (is_array($arg)) |
||
295 | { |
||
296 | $params[] = 'array(' . count($arg) . ')'; |
||
297 | } |
||
298 | else if (is_object($arg)) |
||
299 | { |
||
300 | $params[] = get_class($arg); |
||
301 | } |
||
302 | else if (is_string($arg)) |
||
303 | { |
||
304 | $params[] = 'string(' . (strlen($arg) > 70 ? substr($arg, 0, 70) . '...' : $arg) . ')'; |
||
305 | } |
||
306 | else if (is_int($arg)) |
||
307 | { |
||
308 | $params[] = 'int(' . $arg . ')'; |
||
309 | } |
||
310 | else if (is_float($arg)) |
||
311 | { |
||
312 | $params[] = 'float(' . $arg . ')'; |
||
313 | } |
||
314 | else if (is_bool($arg)) |
||
315 | { |
||
316 | $params[] = 'bool(' . ($arg ? 'true' : 'false') . ')'; |
||
317 | } |
||
318 | else if ($arg instanceof \__PHP_Incomplete_Class) |
||
319 | { |
||
320 | $params[] = 'object(__PHP_Incomplete_Class)'; |
||
321 | } |
||
322 | else |
||
323 | { |
||
324 | $params[] = gettype($arg); |
||
325 | } |
||
326 | } |
||
327 | |||
328 | return $params; |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * @param $path |
||
333 | * @return string |
||
334 | */ |
||
335 | protected function removeProjectRoot($path) |
||
336 | { |
||
337 | if (substr($path, 0, strlen($this->projectRoot)) == $this->projectRoot) |
||
338 | { |
||
339 | return substr($path, strlen($this->projectRoot)); |
||
340 | } |
||
341 | } |
||
342 | } |
||
343 |