Issues (127)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Reflection/Adapter/ReflectionObject.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Roave\BetterReflection\Reflection\Adapter;
6
7
use ReflectionException as CoreReflectionException;
8
use ReflectionObject as CoreReflectionObject;
9
use Roave\BetterReflection\Reflection\ReflectionMethod as BetterReflectionMethod;
10
use Roave\BetterReflection\Reflection\ReflectionObject as BetterReflectionObject;
11
use function array_combine;
12
use function array_map;
13
use function func_num_args;
14
use function sprintf;
15
use function strtolower;
16
17
class ReflectionObject extends CoreReflectionObject
18
{
19
    /** @var BetterReflectionObject */
20
    private $betterReflectionObject;
21
22
    public function __construct(BetterReflectionObject $betterReflectionObject)
23 61
    {
24
        $this->betterReflectionObject = $betterReflectionObject;
25 61
    }
26 61
27
    /**
28
     * {@inheritDoc}
29
     *
30
     * @throws CoreReflectionException
31 1
     */
32
    public static function export($argument, $return = null)
33 1
    {
34
        $output = BetterReflectionObject::createFromInstance($argument)->__toString();
35
36
        if ($return) {
37
            return $output;
38
        }
39 1
40
        echo $output;
41 1
42
        return null;
43
    }
44
45
    /**
46
     * {@inheritDoc}
47 1
     */
48
    public function __toString()
49 1
    {
50
        return $this->betterReflectionObject->__toString();
51
    }
52
53
    /**
54
     * {@inheritDoc}
55 1
     */
56
    public function getName()
57 1
    {
58
        return $this->betterReflectionObject->getName();
59
    }
60
61
    /**
62
     * {@inheritDoc}
63 1
     */
64
    public function isInternal()
65 1
    {
66
        return $this->betterReflectionObject->isInternal();
67
    }
68
69
    /**
70
     * {@inheritDoc}
71 1
     */
72
    public function isUserDefined()
73 1
    {
74
        return $this->betterReflectionObject->isUserDefined();
75
    }
76
77
    /**
78
     * {@inheritDoc}
79 1
     */
80
    public function isInstantiable()
81 1
    {
82
        return $this->betterReflectionObject->isInstantiable();
83
    }
84
85
    /**
86
     * {@inheritDoc}
87 2
     */
88
    public function isCloneable()
89 2
    {
90
        return $this->betterReflectionObject->isCloneable();
91
    }
92
93
    /**
94
     * {@inheritDoc}
95 1
     */
96
    public function getFileName()
97 1
    {
98
        return $this->betterReflectionObject->getFileName() ?? false;
0 ignored issues
show
Comprehensibility Best Practice introduced by Jaroslav Hanslík
The expression $this->betterReflectionO...getFileName() ?? false; of type string|false adds false to the return on line 98 which is incompatible with the return type of the parent method ReflectionObject::getFileName of type string. It seems like you forgot to handle an error condition.
Loading history...
99
    }
100
101
    /**
102
     * {@inheritDoc}
103 1
     */
104
    public function getStartLine()
105 1
    {
106
        return $this->betterReflectionObject->getStartLine();
107
    }
108
109
    /**
110
     * {@inheritDoc}
111 2
     */
112
    public function getEndLine()
113 2
    {
114
        return $this->betterReflectionObject->getEndLine();
115
    }
116
117
    /**
118
     * {@inheritDoc}
119 1
     */
120
    public function getDocComment()
121 1
    {
122
        return $this->betterReflectionObject->getDocComment() ?: false;
0 ignored issues
show
Comprehensibility Best Practice introduced by Jaroslav Hanslík
The expression $this->betterReflectionO...tDocComment() ?: false; of type string|false adds false to the return on line 122 which is incompatible with the return type of the parent method ReflectionObject::getDocComment of type string. It seems like you forgot to handle an error condition.
Loading history...
123
    }
124
125
    /**
126
     * {@inheritDoc}
127 2
     */
128
    public function getConstructor()
129 2
    {
130
        return new ReflectionMethod($this->betterReflectionObject->getConstructor());
131
    }
132
133
    /**
134
     * {@inheritDoc}
135 2
     */
136
    public function hasMethod($name)
137 2
    {
138
        return $this->betterReflectionObject->hasMethod($this->getMethodRealName($name));
139
    }
140 4
141
    /**
142
     * {@inheritDoc}
143 2
     */
144 4
    public function getMethod($name)
145
    {
146
        return new ReflectionMethod($this->betterReflectionObject->getMethod($this->getMethodRealName($name)));
147 2
    }
148 4
149
    private function getMethodRealName(string $name) : string
150 4
    {
151
        $realMethodNames = array_map(static function (BetterReflectionMethod $method) : string {
152
            return $method->getName();
153
        }, $this->betterReflectionObject->getMethods());
154
155
        $methodNames = array_combine(array_map(static function (string $methodName) : string {
156 1
            return strtolower($methodName);
157
        }, $realMethodNames), $realMethodNames);
158 1
159
        return $methodNames[strtolower($name)] ?? $name;
160 1
    }
161 1
162 1
    /**
163
     * {@inheritDoc}
164
     */
165 1
    public function getMethods($filter = null)
166
    {
167
        $methods = $this->betterReflectionObject->getMethods();
168
169
        $wrappedMethods = [];
170
        foreach ($methods as $key => $method) {
171 1
            $wrappedMethods[$key] = new ReflectionMethod($method);
172
        }
173 1
174
        return $wrappedMethods;
175
    }
176
177
    /**
178
     * {@inheritDoc}
179 2
     */
180
    public function hasProperty($name)
181 2
    {
182
        return $this->betterReflectionObject->hasProperty($name);
183 2
    }
184 1
185
    /**
186
     * {@inheritDoc}
187 1
     */
188
    public function getProperty($name)
189
    {
190
        $property = $this->betterReflectionObject->getProperty($name);
191
192
        if ($property === null) {
193 1
            throw new CoreReflectionException(sprintf('Property "%s" does not exist', $name));
194
        }
195 1
196
        return new ReflectionProperty($property);
197 1
    }
198 1
199 1
    /**
200
     * {@inheritDoc}
201
     */
202 1
    public function getProperties($filter = null)
203
    {
204
        $properties = $this->betterReflectionObject->getProperties();
205
206
        $wrappedProperties = [];
207
        foreach ($properties as $key => $property) {
208 1
            $wrappedProperties[$key] = new ReflectionProperty($property);
209
        }
210 1
211
        return $wrappedProperties;
212
    }
213
214
    /**
215
     * {@inheritDoc}
216 1
     */
217
    public function hasConstant($name)
218 1
    {
219
        return $this->betterReflectionObject->hasConstant($name);
220
    }
221
222
    /**
223
     * {@inheritDoc}
224 1
     */
225
    public function getConstants()
226 1
    {
227
        return $this->betterReflectionObject->getConstants();
228
    }
229
230
    /**
231
     * {@inheritDoc}
232 1
     */
233
    public function getConstant($name)
234 1
    {
235
        return $this->betterReflectionObject->getConstant($name);
236 1
    }
237 1
238 1
    /**
239
     * {@inheritDoc}
240
     */
241 1
    public function getInterfaces()
242
    {
243
        $interfaces = $this->betterReflectionObject->getInterfaces();
244
245
        $wrappedInterfaces = [];
246
        foreach ($interfaces as $key => $interface) {
247 1
            $wrappedInterfaces[$key] = new ReflectionClass($interface);
248
        }
249 1
250
        return $wrappedInterfaces;
251
    }
252
253
    /**
254
     * {@inheritDoc}
255 1
     */
256
    public function getInterfaceNames()
257 1
    {
258
        return $this->betterReflectionObject->getInterfaceNames();
259
    }
260
261
    /**
262
     * {@inheritDoc}
263 1
     */
264
    public function isInterface()
265 1
    {
266
        return $this->betterReflectionObject->isInterface();
267 1
    }
268 1
269 1
    /**
270
     * {@inheritDoc}
271
     */
272 1
    public function getTraits()
273
    {
274
        $traits = $this->betterReflectionObject->getTraits();
275
276
        $wrappedTraits = [];
277
        foreach ($traits as $key => $trait) {
278 1
            $wrappedTraits[$key] = new ReflectionClass($trait);
279
        }
280 1
281
        return $wrappedTraits;
282
    }
283
284
    /**
285
     * {@inheritDoc}
286 1
     */
287
    public function getTraitNames()
288 1
    {
289
        return $this->betterReflectionObject->getTraitNames();
290
    }
291
292
    /**
293
     * {@inheritDoc}
294 1
     */
295
    public function getTraitAliases()
296 1
    {
297
        return $this->betterReflectionObject->getTraitAliases();
298
    }
299
300
    /**
301
     * {@inheritDoc}
302 1
     */
303
    public function isTrait()
304 1
    {
305
        return $this->betterReflectionObject->isTrait();
306
    }
307
308
    /**
309
     * {@inheritDoc}
310 1
     */
311
    public function isAbstract()
312 1
    {
313
        return $this->betterReflectionObject->isAbstract();
314
    }
315
316
    /**
317
     * {@inheritDoc}
318 1
     */
319
    public function isFinal()
320 1
    {
321
        return $this->betterReflectionObject->isFinal();
322
    }
323
324
    /**
325
     * {@inheritDoc}
326 1
     */
327
    public function getModifiers()
328 1
    {
329
        return $this->betterReflectionObject->getModifiers();
330
    }
331
332
    /**
333
     * {@inheritDoc}
334 1
     */
335
    public function isInstance($object)
336 1
    {
337
        return $this->betterReflectionObject->isInstance($object);
338
    }
339
340
    /**
341
     * {@inheritDoc}
342 1
     */
343
    public function newInstance($arg = null, ...$args)
0 ignored issues
show
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
344 1
    {
345
        throw new Exception\NotImplemented('Not implemented');
346
    }
347
348
    /**
349
     * {@inheritDoc}
350 1
     */
351
    public function newInstanceWithoutConstructor()
352 1
    {
353
        throw new Exception\NotImplemented('Not implemented');
354
    }
355
356
    /**
357
     * {@inheritDoc}
358 2
     */
359
    public function newInstanceArgs(?array $args = null)
360 2
    {
361
        throw new Exception\NotImplemented('Not implemented');
362 2
    }
363 1
364
    /**
365
     * {@inheritDoc}
366 1
     */
367
    public function getParentClass()
368
    {
369
        $parentClass = $this->betterReflectionObject->getParentClass();
370
371
        if ($parentClass === null) {
372 2
            return false;
0 ignored issues
show
Bug Best Practice introduced by Jaroslav Hanslík
The return type of return false; (false) is incompatible with the return type of the parent method ReflectionObject::getParentClass of type object.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
373
        }
374 2
375
        return new ReflectionClass($parentClass);
376
    }
377 1
378 2
    /**
379
     * {@inheritDoc}
380 2
     */
381
    public function isSubclassOf($class)
382 2
    {
383
        $realParentClassNames = $this->betterReflectionObject->getParentClassNames();
384
385
        $parentClassNames = array_combine(array_map(static function (string $parentClassName) : string {
386
            return strtolower($parentClassName);
387
        }, $realParentClassNames), $realParentClassNames);
388 1
389
        $realParentClassName = $parentClassNames[strtolower($class)] ?? $class;
390 1
391
        return $this->betterReflectionObject->isSubclassOf($realParentClassName);
392
    }
393
394
    /**
395
     * {@inheritDoc}
396 4
     */
397
    public function getStaticProperties()
398 4
    {
399
        return $this->betterReflectionObject->getStaticProperties();
400 4
    }
401 2
402 1
    /**
403
     * {@inheritDoc}
404
     */
405 1
    public function getStaticPropertyValue($name, $default = null)
406
    {
407
        $betterReflectionProperty = $this->betterReflectionObject->getProperty($name);
408 2
409
        if ($betterReflectionProperty === null) {
410 2
            if (func_num_args() === 2) {
411 1
                return $default;
412
            }
413
414 1
            throw new CoreReflectionException(sprintf('Property "%s" does not exist', $name));
415
        }
416
417
        $property = new ReflectionProperty($betterReflectionProperty);
418 1
419
        if (! $property->isAccessible()) {
420
            throw new CoreReflectionException(sprintf('Property "%s" is not accessible', $name));
421
        }
422
423
        if (! $property->isStatic()) {
424 3
            throw new CoreReflectionException(sprintf('Property "%s" is not static', $name));
425
        }
426 3
427
        return $property->getValue();
428 3
    }
429 1
430
    /**
431
     * {@inheritDoc}
432 2
     */
433
    public function setStaticPropertyValue($name, $value)
434 2
    {
435 1
        $betterReflectionProperty = $this->betterReflectionObject->getProperty($name);
436
437
        if ($betterReflectionProperty === null) {
438 1
            throw new CoreReflectionException(sprintf('Property "%s" does not exist', $name));
439
        }
440
441
        $property = new ReflectionProperty($betterReflectionProperty);
442 1
443 1
        if (! $property->isAccessible()) {
444
            throw new CoreReflectionException(sprintf('Property "%s" is not accessible', $name));
445
        }
446
447
        if (! $property->isStatic()) {
448 1
            throw new CoreReflectionException(sprintf('Property "%s" is not static', $name));
449
        }
450 1
451
        $property->setValue($value);
452
    }
453
454
    /**
455
     * {@inheritDoc}
456 1
     */
457
    public function getDefaultProperties()
458 1
    {
459
        return $this->betterReflectionObject->getDefaultProperties();
460
    }
461
462
    /**
463
     * {@inheritDoc}
464 2
     */
465
    public function isIterateable()
466 2
    {
467
        return $this->betterReflectionObject->isIterateable();
468
    }
469 1
470 2
    /**
471
     * {@inheritDoc}
472 2
     */
473
    public function implementsInterface($interface)
474 2
    {
475
        $realInterfaceNames = $this->betterReflectionObject->getInterfaceNames();
476
477
        $interfaceNames = array_combine(array_map(static function (string $interfaceName) : string {
478
            return strtolower($interfaceName);
479
        }, $realInterfaceNames), $realInterfaceNames);
480 1
481
        $realInterfaceName = $interfaceNames[strtolower($interface)] ?? $interface;
482 1
483
        return $this->betterReflectionObject->implementsInterface($realInterfaceName);
484
    }
485
486
    /**
487
     * {@inheritDoc}
488 2
     */
489
    public function getExtension()
490 2
    {
491
        throw new Exception\NotImplemented('Not implemented');
492
    }
493
494
    /**
495
     * {@inheritDoc}
496 1
     */
497
    public function getExtensionName()
498 1
    {
499
        return $this->betterReflectionObject->getExtensionName() ?? false;
0 ignored issues
show
Bug Best Practice introduced by Jaroslav Hanslík
The return type of return $this->betterRefl...tensionName() ?? false; (false) is incompatible with the return type of the parent method ReflectionObject::getExtensionName of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
500
    }
501
502
    /**
503
     * {@inheritDoc}
504 1
     */
505
    public function inNamespace()
506 1
    {
507
        return $this->betterReflectionObject->inNamespace();
508
    }
509
510
    /**
511
     * {@inheritDoc}
512 1
     */
513
    public function getNamespaceName()
514 1
    {
515
        return $this->betterReflectionObject->getNamespaceName();
516
    }
517
518
    /**
519
     * {@inheritDoc}
520
     */
521
    public function getShortName()
522
    {
523
        return $this->betterReflectionObject->getShortName();
524
    }
525
}
526