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 | * PHP Smart Analysis project 2015-2016 |
||
4 | * |
||
5 | * @author Patsura Dmitry https://github.com/ovr <[email protected]> |
||
6 | */ |
||
7 | |||
8 | namespace PHPSA\Compiler\Expression; |
||
9 | |||
10 | use Ovr\PHPReflection\Reflector; |
||
11 | use PHPSA\CompiledExpression; |
||
12 | use PHPSA\Context; |
||
13 | use PHPSA\Definition\ClosureDefinition; |
||
14 | |||
15 | class FunctionCall extends AbstractExpressionCompiler |
||
16 | { |
||
17 | protected $name = 'PhpParser\Node\Expr\FuncCall'; |
||
18 | |||
19 | /** |
||
20 | * @param \PhpParser\Node\Expr\FuncCall $expr |
||
21 | * @param Context $context |
||
22 | * @return CompiledExpression |
||
23 | */ |
||
24 | protected function compile($expr, Context $context) |
||
0 ignored issues
–
show
|
|||
25 | { |
||
26 | $expressionCompiler = $context->getExpressionCompiler(); |
||
27 | $fNameExpression = $expressionCompiler->compile($expr->name); |
||
28 | $name = $fNameExpression->getValue(); |
||
29 | |||
30 | $compiler = $context->application->compiler; |
||
31 | $exists = false; |
||
0 ignored issues
–
show
$exists is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
32 | $arguments = $this->parseArgs($expr, clone $context); |
||
33 | |||
34 | // is it a Closure |
||
35 | if ($fNameExpression->isCallable() && $name instanceof ClosureDefinition) { |
||
36 | return $name->run($this->parseArgs($expr, clone $context), $context); |
||
37 | } |
||
38 | |||
39 | // is the function name a correct string |
||
40 | if (!$fNameExpression->isString() || !$fNameExpression->isCorrectValue()) { |
||
41 | $context->debug( |
||
42 | 'Unexpected function name type ' . $fNameExpression->getTypeName(), |
||
43 | $expr->name |
||
44 | ); |
||
45 | |||
46 | return new CompiledExpression(); |
||
47 | } |
||
48 | |||
49 | // namespace check for correct functionDefinition |
||
50 | if ($context->scope) { |
||
51 | $functionDefinition = $compiler->getFunctionNS($name, $context->scope->getNamespace()); |
||
0 ignored issues
–
show
The method
getNamespace() does not exist on PHPSA\Definition\AbstractDefinition . Did you maybe mean getName() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
52 | } else { |
||
53 | $functionDefinition = $compiler->getFunction($name); |
||
54 | } |
||
55 | |||
56 | // does the function exist |
||
57 | if ($functionDefinition) { |
||
58 | if (!$functionDefinition->isCompiled()) { |
||
59 | $functionDefinition->compile(clone $context); |
||
60 | } |
||
61 | |||
62 | $exists = true; |
||
63 | } else { |
||
64 | $exists = function_exists($name); |
||
65 | } |
||
66 | |||
67 | if (!$exists) { |
||
68 | $context->notice( |
||
69 | 'language_error', |
||
70 | sprintf('Function %s() does not exist', (string)$expr->name), |
||
71 | $expr |
||
72 | ); |
||
73 | } else { |
||
74 | $reflector = new Reflector(Reflector::manuallyFactory()); |
||
75 | $functionReflection = $reflector->getFunction($name); |
||
76 | if ($functionReflection) { |
||
77 | $argumentsSuccessPass = $this->checkArguments($arguments, $functionReflection); |
||
0 ignored issues
–
show
It seems like
$functionReflection defined by $reflector->getFunction($name) on line 75 can also be of type boolean ; however, PHPSA\Compiler\Expressio...nCall::checkArguments() does only seem to accept object<Ovr\PHPReflection\FunctionReflection> , 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. ![]() |
|||
78 | |||
79 | // when everything is ok we run the function |
||
80 | if ($argumentsSuccessPass && $functionReflection->isRunnable()) { |
||
81 | array_walk( |
||
82 | $arguments, |
||
83 | function (&$item) { |
||
84 | /** @var CompiledExpression $item */ |
||
85 | $item = $item->getValue(); |
||
86 | } |
||
87 | ); |
||
88 | |||
89 | return new CompiledExpression( |
||
90 | $functionReflection->getReturnType(), |
||
91 | $functionReflection->run($arguments) |
||
92 | ); |
||
93 | } |
||
94 | |||
95 | return new CompiledExpression($functionReflection->getReturnType()); |
||
96 | } |
||
97 | } |
||
98 | |||
99 | return new CompiledExpression(); |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * @param \PhpParser\Node\Expr\FuncCall $expr |
||
104 | * @return CompiledExpression[] |
||
105 | */ |
||
106 | protected function parseArgs($expr, Context $context) |
||
107 | { |
||
108 | $arguments = []; |
||
109 | |||
110 | foreach ($expr->args as $argument) { |
||
111 | $arguments[] = $context->getExpressionCompiler()->compile($argument->value); |
||
112 | } |
||
113 | |||
114 | return $arguments; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * @param CompiledExpression[] $arguments |
||
119 | * @param \Ovr\PHPReflection\FunctionReflection $functionReflection |
||
120 | * @return bool |
||
121 | */ |
||
122 | protected function checkArguments(array $arguments, $functionReflection) |
||
123 | { |
||
124 | foreach ($arguments as $key => $argument) { |
||
125 | $parameter = $functionReflection->getParameter($key); |
||
126 | $paramType = $parameter->getType(); |
||
127 | $argumentType = $argument->getType(); |
||
128 | |||
129 | $numberTypes = [CompiledExpression::INTEGER, CompiledExpression::DOUBLE]; |
||
130 | $callableTypes = [CompiledExpression::STRING, CompiledExpression::ARR]; |
||
131 | |||
132 | // the paramtype is equal to the argument type or mixed |
||
133 | // or paramtype is number and argumenttype is integer, double |
||
134 | // or paramtype is callable and argumenttype is string, array |
||
135 | if (!($paramType == $argumentType || $paramType == CompiledExpression::MIXED) |
||
136 | && !($paramType == CompiledExpression::NUMBER && in_array($argumentType, $numberTypes)) |
||
137 | && !($paramType == CompiledExpression::CALLABLE_TYPE && in_array($argumentType, $callableTypes))) { |
||
138 | return false; |
||
139 | } |
||
140 | } |
||
141 | |||
142 | // argumentcount != paramcount |
||
143 | if (count($arguments) != $functionReflection->getNumberOfRequiredParameters()) { |
||
144 | return false; |
||
145 | } |
||
146 | |||
147 | return true; |
||
148 | } |
||
149 | } |
||
150 |
A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.
You can also find more information in the “Code” section of your repository.