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 | class Ajde_Exception_Handler extends Ajde_Object_Static |
||
4 | { |
||
5 | const EXCEPTION_TRACE_HTML = 1; |
||
6 | const EXCEPTION_TRACE_ONLY = 3; |
||
7 | const EXCEPTION_TRACE_LOG = 2; |
||
8 | |||
9 | public static function __bootstrap() |
||
10 | { |
||
11 | // making xdebug.overload_var_dump = 1 work |
||
12 | if (config('app.debug')) { |
||
13 | ini_set('html_errors', 1); |
||
14 | } |
||
15 | |||
16 | set_error_handler(['Ajde_Exception_Handler', 'errorHandler']); |
||
17 | set_exception_handler(['Ajde_Exception_Handler', 'handler']); |
||
18 | |||
19 | return true; |
||
20 | } |
||
21 | |||
22 | public static function errorHandler($errno, $errstr, $errfile, $errline) |
||
23 | { |
||
24 | if (error_reporting() > 0) { |
||
25 | $message = sprintf('PHP error: %s in %s on line %s', $errstr, $errfile, $errline); |
||
26 | error_log($message); |
||
27 | dump($message); |
||
28 | |||
29 | // TODO: only possible in PHP >= 5.3 ? |
||
30 | // try |
||
31 | // { |
||
32 | throw new ErrorException($errstr, 0, $errno, $errfile, $errline); |
||
33 | // } catch(Exception $exception) { |
||
34 | // } |
||
35 | } |
||
36 | } |
||
37 | |||
38 | /** |
||
39 | * @param Throwable $exception |
||
40 | */ |
||
41 | public static function handler($exception) |
||
0 ignored issues
–
show
|
|||
42 | { |
||
43 | try { |
||
44 | if (config('app.debug') === true) { |
||
45 | if (!((get_class($exception) == 'Ajde_Exception' || is_subclass_of($exception, 'Ajde_Exception')) && !$exception->traceOnOutput()) |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Exception as the method traceOnOutput() does only exist in the following sub-classes of Exception : Ajde_Component_Exception , Ajde_Controller_Exception , Ajde_Core_Autoloader_Exception , Ajde_Core_Exception_Deprecated , Ajde_Core_Exception_Routing , Ajde_Core_Exception_Security , Ajde_Db_Exception , Ajde_Db_IntegrityException , Ajde_Exception . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
46 | ) { |
||
47 | Ajde_Exception_Log::logException($exception); |
||
0 ignored issues
–
show
It seems like
$exception can also be of type object<Exception> ; however, Ajde_Exception_Log::logException() does only seem to accept object<Throwable> , 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. ![]() |
|||
48 | echo self::trace($exception); |
||
0 ignored issues
–
show
It seems like
$exception can also be of type object<Exception> ; however, Ajde_Exception_Handler::trace() does only seem to accept object<Throwable> , 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. ![]() |
|||
49 | } else { |
||
50 | Ajde_Exception_Log::logException($exception); |
||
0 ignored issues
–
show
It seems like
$exception can also be of type object<Exception> ; however, Ajde_Exception_Log::logException() does only seem to accept object<Throwable> , 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. ![]() |
|||
51 | Ajde_Http_Response::redirectServerError(); |
||
52 | } |
||
53 | } else { |
||
54 | Ajde_Exception_Log::logException($exception); |
||
0 ignored issues
–
show
It seems like
$exception can also be of type object<Exception> ; however, Ajde_Exception_Log::logException() does only seem to accept object<Throwable> , 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. ![]() |
|||
55 | Ajde_Http_Response::redirectServerError(); |
||
56 | } |
||
57 | } catch (Exception $exception) { |
||
58 | error_log(self::trace($exception, self::EXCEPTION_TRACE_LOG)); |
||
0 ignored issues
–
show
$exception is of type object<Exception> , but the function expects a object<Throwable> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
59 | die('An uncatched exception occured within the error handler, see the server error_log for details'); |
||
60 | } |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * @param Throwable $exception |
||
65 | * @param int $output |
||
66 | * |
||
67 | * @return string |
||
68 | */ |
||
69 | public static function trace($exception, $output = self::EXCEPTION_TRACE_HTML) |
||
70 | { |
||
71 | $simpleJsonTrace = false; |
||
72 | if ($simpleJsonTrace && Ajde::app()->hasDocument() && Ajde::app()->getDocument()->getFormat() == 'json') { |
||
0 ignored issues
–
show
The method
hasDocument does not exist on object<Ajde_Application> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() The method
getFormat does not exist on object<Ajde_Document> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when class ParentClass {
private $data = array();
public function __call($method, array $args) {
if (0 === strpos($method, 'get')) {
return $this->data[strtolower(substr($method, 3))];
}
throw new \LogicException(sprintf('Unsupported method: %s', $method));
}
}
/**
* If this class knows which fields exist, you can specify the methods here:
*
* @method string getName()
*/
class SomeClass extends ParentClass { }
![]() |
|||
73 | $output = self::EXCEPTION_TRACE_LOG; |
||
74 | } |
||
75 | |||
76 | $type = self::getTypeDescription($exception); |
||
77 | |||
78 | switch ($output) { |
||
79 | case self::EXCEPTION_TRACE_HTML: |
||
80 | if (ob_get_level()) { |
||
81 | ob_clean(); |
||
82 | } |
||
83 | |||
84 | $traceMessage = '<ol reversed="reversed">'; |
||
85 | self::$firstApplicationFileExpanded = false; |
||
86 | foreach ($exception->getTrace() as $item) { |
||
87 | $arguments = null; |
||
88 | if (!empty($item['args'])) { |
||
89 | ob_start(); |
||
90 | var_dump($item['args']); |
||
0 ignored issues
–
show
|
|||
91 | $dump = ob_get_clean(); |
||
92 | $arguments = sprintf(' with arguments: %s', $dump); |
||
93 | } |
||
94 | $traceMessage .= sprintf("<li><code><em>%s</em>%s<strong>%s</strong></code><br/>in %s<br/> \n", |
||
95 | !empty($item['class']) ? $item['class'] : '<unknown class>', |
||
96 | !empty($item['type']) ? $item['type'] : '::', |
||
97 | !empty($item['function']) ? $item['function'] : '<unknown function>', |
||
98 | self::embedScript( |
||
99 | issetor($item['file'], null), |
||
100 | issetor($item['line'], null), |
||
101 | $arguments, |
||
102 | false |
||
103 | )); |
||
104 | $traceMessage .= '</li>'; |
||
105 | } |
||
106 | $traceMessage .= '</ol>'; |
||
107 | |||
108 | $exceptionDocumentation = ''; |
||
109 | if ($exception instanceof Ajde_Exception && $exception->getCode()) { |
||
110 | $exceptionDocumentation = sprintf("<div style='margin-top: 4px;'><img src='".config('app.rootUrl').MEDIA_DIR."_core/globe_16.png' style='vertical-align: bottom;' title='Primary key' width='16' height='16' /> <a href='%s'>Documentation on error %s</a> </div>", |
||
111 | Ajde_Core_Documentation::getUrl($exception->getCode()), |
||
112 | $exception->getCode() |
||
113 | ); |
||
114 | } |
||
115 | |||
116 | $exceptionMessage = sprintf("<summary style='background-image: url(\"".config('app.rootUrl').MEDIA_DIR."_core/warning_48.png\");'><h3 style='margin:0;'>%s:</h3><h2 style='margin:0;'>%s</h2> Exception thrown in %s%s</summary><h3>Trace:</h3>\n", |
||
117 | $type, |
||
118 | $exception->getMessage(), |
||
119 | self::embedScript( |
||
120 | $exception->getFile(), |
||
121 | $exception->getLine(), |
||
122 | $arguments, |
||
0 ignored issues
–
show
The variable
$arguments does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
123 | false //!self::$firstApplicationFileExpanded |
||
124 | ), |
||
125 | $exceptionDocumentation |
||
126 | ); |
||
127 | |||
128 | $exceptionDump = ''; |
||
129 | if (class_exists(Ajde_Dump::class)) { |
||
130 | if ($dumps = Ajde_Dump::getAll()) { |
||
131 | $exceptionDump .= '<h2>Dumps</h2>'; |
||
132 | foreach ($dumps as $source => $dump) { |
||
133 | ob_start(); |
||
134 | echo $source; |
||
135 | if (class_exists(Kint::class)) { |
||
136 | Kint::dump($dump[0]); |
||
137 | } else { |
||
138 | echo '<pre>'; |
||
139 | var_dump($dump[0]); |
||
140 | echo '</pre>'; |
||
141 | } |
||
142 | $exceptionDump .= ob_get_clean().'<h2>Error message</h2>'; |
||
143 | } |
||
144 | } |
||
145 | } |
||
146 | |||
147 | $style = false; |
||
148 | if (file_exists(LOCAL_ROOT.CORE_DIR.MODULE_DIR.'_core/res/css/debugger/handler.css')) { |
||
149 | $style = file_get_contents(LOCAL_ROOT.CORE_DIR.MODULE_DIR.'_core/res/css/debugger/handler.css'); |
||
150 | } |
||
151 | if ($style === false) { |
||
152 | // For shutdown() call |
||
153 | $style = 'body {font: 13px sans-serif;} a {color: #005D9A;} a:hover {color: #9A0092;} h2 {color: #005D9A;} span > a {color: #9A0092;}'; |
||
154 | } |
||
155 | $style = '<style>'.$style.'</style>'; |
||
156 | $script = '<script>document.getElementsByTagName("base")[0].href="";</script>'; |
||
157 | |||
158 | if (Ajde::app()->getRequest()->isAjax()) { |
||
159 | $collapsed = $exceptionDump.$exceptionMessage.$traceMessage; |
||
160 | $header = ''; |
||
161 | } else { |
||
162 | $collapsed = '<div id="details">'.$exceptionDump.$exceptionMessage.$traceMessage.'</div>'; |
||
163 | $header = '<header><h1><img src="'.config('app.rootUrl').MEDIA_DIR.'ajde-small.png">Something went wrong</h1><a href="javascript:history.go(-1);">Go back</a> <a href="#details">Show details</a></header>'; |
||
164 | } |
||
165 | |||
166 | $message = $style.$script.$header.$collapsed; |
||
167 | break; |
||
168 | case self::EXCEPTION_TRACE_ONLY: |
||
169 | $message = ''; |
||
170 | View Code Duplication | foreach (array_reverse($exception->getTrace()) as $i => $line) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
171 | $message .= $i.'. '.(isset($line['file']) ? $line['file'] : 'unknown file').' on line '.(isset($line['line']) ? $line['line'] : 'unknown line'); |
||
172 | $message .= PHP_EOL; |
||
173 | } |
||
174 | break; |
||
175 | case self::EXCEPTION_TRACE_LOG: |
||
176 | $message = 'UNCAUGHT EXCEPTION'.PHP_EOL; |
||
177 | $message .= "\tRequest ".$_SERVER['REQUEST_URI'].' triggered:'.PHP_EOL; |
||
178 | $message .= sprintf("\t%s: %s in %s on line %s", |
||
179 | $type, |
||
180 | $exception->getMessage(), |
||
181 | $exception->getFile(), |
||
182 | $exception->getLine() |
||
183 | ); |
||
184 | View Code Duplication | foreach (array_reverse($exception->getTrace()) as $i => $line) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
185 | $message .= PHP_EOL; |
||
186 | $message .= "\t".$i.'. '.(isset($line['file']) ? $line['file'] : 'unknown file').' on line '.(isset($line['line']) ? $line['line'] : 'unknown line'); |
||
187 | } |
||
188 | break; |
||
189 | } |
||
190 | |||
191 | return $message; |
||
0 ignored issues
–
show
The variable
$message does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
192 | } |
||
193 | |||
194 | /** |
||
195 | * @param Throwable $exception |
||
196 | * |
||
197 | * @return string |
||
198 | */ |
||
199 | public static function getTypeDescription($exception) |
||
200 | { |
||
201 | if ($exception instanceof ErrorException) { |
||
202 | $type = 'PHP Error '.self::getErrorType($exception->getSeverity()); |
||
203 | } elseif ($exception instanceof Ajde_Exception) { |
||
204 | $type = 'Application exception'.($exception->getCode() ? ' '.$exception->getCode() : ''); |
||
205 | } else { |
||
206 | $type = 'PHP exception '.$exception->getCode(); |
||
207 | } |
||
208 | |||
209 | return $type; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * @param Throwable $exception |
||
214 | * |
||
215 | * @return string |
||
216 | */ |
||
217 | View Code Duplication | public static function getExceptionChannelMap($exception) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
218 | { |
||
219 | if ($exception instanceof ErrorException) { |
||
220 | return Ajde_Log::CHANNEL_ERROR; |
||
221 | } elseif ($exception instanceof Ajde_Core_Exception_Routing) { |
||
222 | return Ajde_Log::CHANNEL_ROUTING; |
||
223 | } elseif ($exception instanceof Ajde_Core_Exception_Security) { |
||
224 | return Ajde_Log::CHANNEL_SECURITY; |
||
225 | } elseif ($exception instanceof Ajde_Exception) { |
||
226 | return Ajde_Log::CHANNEL_APPLICATION; |
||
227 | } else { |
||
228 | return Ajde_Log::CHANNEL_EXCEPTION; |
||
229 | } |
||
230 | } |
||
231 | |||
232 | /** |
||
233 | * @param Throwable $exception |
||
234 | * |
||
235 | * @return string |
||
236 | */ |
||
237 | View Code Duplication | public static function getExceptionLevelMap($exception) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
238 | { |
||
239 | if ($exception instanceof ErrorException) { |
||
240 | return Ajde_Log::LEVEL_ERROR; |
||
241 | } elseif ($exception instanceof Ajde_Core_Exception_Routing) { |
||
242 | return Ajde_Log::LEVEL_WARNING; |
||
243 | } elseif ($exception instanceof Ajde_Core_Exception_Security) { |
||
244 | return Ajde_Log::LEVEL_WARNING; |
||
245 | } elseif ($exception instanceof Ajde_Exception) { |
||
246 | return Ajde_Log::LEVEL_ERROR; |
||
247 | } else { |
||
248 | return Ajde_Log::LEVEL_ERROR; |
||
249 | } |
||
250 | } |
||
251 | |||
252 | public static function getErrorType($type) |
||
253 | { |
||
254 | switch ($type) { |
||
255 | case 1: |
||
256 | return 'E_ERROR'; |
||
257 | case 2: |
||
258 | return 'E_WARNING'; |
||
259 | case 4: |
||
260 | return 'E_PARSE'; |
||
261 | case 8: |
||
262 | return 'E_NOTICE'; |
||
263 | case 16: |
||
264 | return 'E_CORE_ERROR'; |
||
265 | case 32: |
||
266 | return 'E_CORE_WARNING'; |
||
267 | case 64: |
||
268 | return 'E_COMPILE_ERROR'; |
||
269 | case 128: |
||
270 | return 'E_COMPILE_WARNING'; |
||
271 | case 256: |
||
272 | return 'E_USER_ERROR'; |
||
273 | case 512: |
||
274 | return 'E_USER_WARNING'; |
||
275 | case 1024: |
||
276 | return 'E_USER_NOTICE'; |
||
277 | case 2048: |
||
278 | return 'E_STRICT'; |
||
279 | case 4096: |
||
280 | return 'E_RECOVERABLE_ERROR'; |
||
281 | case 8192: |
||
282 | return 'E_DEPRECATED'; |
||
283 | case 16384: |
||
284 | return 'E_USER_DEPRECATED'; |
||
285 | case 30719: |
||
286 | return 'E_ALL'; |
||
287 | } |
||
288 | } |
||
289 | |||
290 | public static $firstApplicationFileExpanded = false; |
||
291 | |||
292 | protected static function embedScript($filename = null, $line = null, $arguments = null, $expand = false) |
||
293 | { |
||
294 | $lineOffset = 5; |
||
295 | $file = ''; |
||
296 | |||
297 | // in case of eval, filename looks like File.php(30) : eval()'d code |
||
298 | if (substr_count($filename, '(')) { |
||
299 | list($filename) = explode('(', $filename); |
||
300 | } |
||
301 | |||
302 | if (isset($filename) && isset($line)) { |
||
303 | $lines = file($filename); |
||
304 | for ($i = max(0, $line - $lineOffset - 1); $i < min($line + $lineOffset, count($lines)); $i++) { |
||
305 | $lineNumber = str_repeat(' ', 4 - strlen($i + 1)).($i + 1); |
||
306 | if ($i == $line - 1) { |
||
307 | $file .= '{{{}}}'.$lineNumber.' '.($lines[$i]).'{{{/}}}'; |
||
308 | } else { |
||
309 | $file .= $lineNumber.' '.($lines[$i]); |
||
310 | } |
||
311 | } |
||
312 | } |
||
313 | |||
314 | if (substr_count($filename, str_replace('/', DIRECTORY_SEPARATOR, APP_DIR))) { |
||
315 | $filename = '<span style="color: red;">'.$filename.'</span>'; |
||
316 | if (self::$firstApplicationFileExpanded === false) { |
||
317 | $expand = true; |
||
318 | } |
||
319 | self::$firstApplicationFileExpanded = true; |
||
320 | } |
||
321 | $file = highlight_string('<?php'.$file, true); |
||
322 | $file = str_replace('<?php', '', $file); |
||
323 | $file = str_replace('<code>', |
||
324 | "<code style='display:block;border:1px solid silver;margin:5px 0 5px 0;background-color:#f1f1f1;'>", $file); |
||
325 | $file = str_replace('{{{}}}', "<div style='background-color: #ffff9e;'>", $file); |
||
326 | $file = str_replace('{{{/}}}', '</div>', $file); |
||
327 | |||
328 | $id = md5(microtime().$filename.$line); |
||
329 | |||
330 | return sprintf( |
||
331 | "<a |
||
332 | onclick='document.getElementById(\"$id\").style.display = document.getElementById(\"$id\").style.display == \"block\" ? \"none\" : \"block\";' |
||
333 | href='javascript:void(0);' |
||
334 | ><i>%s</i> on line <b>%s</b></a> <div id='$id' style='display:%s;'>%s%s</div>", |
||
335 | $filename, |
||
336 | $line, |
||
337 | $expand ? 'block' : 'none', |
||
338 | $file, |
||
339 | $arguments |
||
340 | ); |
||
341 | } |
||
342 | } |
||
343 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.