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 | namespace nochso\Omni; |
||
3 | |||
4 | /** |
||
5 | * Exec creates objects that help manage `\exec()` calls. |
||
6 | * |
||
7 | * The returned object itself is callable, which is the same as calling `run()`. |
||
8 | * |
||
9 | * Arguments are automatically escaped if needed. |
||
10 | * |
||
11 | * Methods `run()`, `create()` and `__invoke()` take any amount of arguments. |
||
12 | * If you have an array of arguments, unpack it first: `run(...$args)` |
||
13 | * |
||
14 | * @see \nochso\Omni\OS::hasBinary Check if the binary/command is available before you run it. |
||
15 | */ |
||
16 | class Exec { |
||
17 | /** |
||
18 | * @var string[] |
||
19 | */ |
||
20 | private $prefixes; |
||
21 | /** |
||
22 | * @var string[] |
||
23 | */ |
||
24 | private $output; |
||
25 | /** |
||
26 | * @var int |
||
27 | */ |
||
28 | private $status; |
||
29 | /** |
||
30 | * @var string |
||
31 | */ |
||
32 | private $lastCommand; |
||
33 | |||
34 | /** |
||
35 | * Create a new callable `Exec` object. |
||
36 | * |
||
37 | * @param string[] $prefixes,... Optional arguments will always be added to the beginning of the command. |
||
38 | * |
||
39 | * @return \nochso\Omni\Exec |
||
40 | */ |
||
41 | public static function create(...$prefixes) { |
||
42 | $exec = new self(); |
||
43 | $exec->prefixes = $prefixes; |
||
44 | return $exec; |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * Run a command with auto-escaped arguments. |
||
49 | * |
||
50 | * @param string[] $arguments,... Optional arguments will be added after the prefixes. |
||
51 | * |
||
52 | * @return $this |
||
53 | */ |
||
54 | public function run(...$arguments) { |
||
55 | $this->lastCommand = $this->getCommand(...$arguments); |
||
56 | exec($this->lastCommand, $output, $status); |
||
57 | $this->output = $output; |
||
0 ignored issues
–
show
|
|||
58 | $this->status = $status; |
||
59 | return $this; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * getCommand returns the string to be used by `\exec()`. |
||
64 | * |
||
65 | * @param string[] $arguments,... |
||
66 | * |
||
67 | * @return string |
||
68 | */ |
||
69 | public function getCommand(...$arguments) { |
||
70 | $command = []; |
||
71 | $allArguments = array_merge($this->prefixes, $arguments); |
||
72 | if (count($allArguments) === 0) { |
||
73 | $allArguments[] = ''; |
||
74 | } |
||
75 | foreach ($allArguments as $argument) { |
||
76 | $command[] = $this->escapeArgument($argument); |
||
77 | } |
||
78 | $commandString = implode(' ', $command); |
||
79 | return $commandString; |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * getLastCommand returns the string last used by a previous call to `run()`. |
||
84 | * |
||
85 | * @return string|null |
||
86 | */ |
||
87 | public function getLastCommand() { |
||
88 | return $this->lastCommand; |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * getOutput of last execution. |
||
93 | * |
||
94 | * @return string[] |
||
95 | */ |
||
96 | public function getOutput() { |
||
97 | return $this->output; |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * getStatus code of last execution. |
||
102 | * |
||
103 | * @return int |
||
104 | */ |
||
105 | public function getStatus() { |
||
106 | return $this->status; |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * __invoke allows using this object as a callable by calling `run()`. |
||
111 | * |
||
112 | * e.g. `$runner('argument');` |
||
113 | * |
||
114 | * @param array $arguments,... |
||
115 | * |
||
116 | * @return \nochso\Omni\Exec |
||
117 | */ |
||
118 | public function __invoke(...$arguments) { |
||
119 | return $this->run(...$arguments); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @param string $argument |
||
124 | * |
||
125 | * @return string |
||
126 | */ |
||
127 | private function escapeArgument($argument) { |
||
128 | // Always escape an empty argument so it doesn't get lost. |
||
129 | if ($argument === '') { |
||
130 | return escapeshellarg($argument); |
||
131 | } |
||
132 | if (!OS::isWindows()) { |
||
133 | return $this->escapeLinuxArgument($argument); |
||
134 | } |
||
135 | return $this->escapeWindowsArgument($argument); |
||
136 | } |
||
137 | |||
138 | /** |
||
139 | * @param string $argument |
||
140 | * |
||
141 | * @return string |
||
142 | */ |
||
143 | private function escapeLinuxArgument($argument) { |
||
144 | $escapedArgument = escapeshellarg($argument); |
||
145 | // Is escaping really needed? |
||
146 | if ($argument !== '--' && mb_substr($escapedArgument, 1, -1) === $argument && preg_match('/^[a-z0-9-]+$/i', $argument) === 1) { |
||
147 | return $argument; |
||
148 | } |
||
149 | return $escapedArgument; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param string $argument |
||
154 | * |
||
155 | * @return string |
||
156 | * |
||
157 | * @link https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ |
||
158 | */ |
||
159 | private function escapeWindowsArgument($argument) { |
||
160 | // Check if there's anything to escape |
||
161 | if (strpbrk($argument, " \t\n\v\"\\") === false) { |
||
162 | return $argument; |
||
163 | } |
||
164 | $escapedArgument = '"'; |
||
165 | $strlen = mb_strlen($argument); |
||
166 | for ($i = 0; $i < $strlen; $i++) { |
||
167 | $backslashes = 0; |
||
168 | while ($i < $strlen && mb_substr($argument, $i, 1) === '\\') { |
||
169 | $i++; |
||
170 | $backslashes++; |
||
171 | } |
||
172 | if ($i === $strlen) { |
||
173 | // Escape all backslashes, but let the terminating double quote be interpreted as a meta character |
||
174 | $escapedArgument .= str_repeat('\\', $backslashes * 2); |
||
175 | } elseif (mb_substr($argument, $i, 1) === '"') { |
||
176 | // Escape all backslashes and the following quotation mark |
||
177 | $escapedArgument .= str_repeat('\\', $backslashes * 2 + 1); |
||
178 | $escapedArgument .= '"'; |
||
179 | } else { |
||
180 | $escapedArgument .= str_repeat('\\', $backslashes); |
||
181 | $escapedArgument .= mb_substr($argument, $i, 1); |
||
182 | } |
||
183 | } |
||
184 | $escapedArgument .= '"'; |
||
185 | return $escapedArgument; |
||
186 | } |
||
187 | } |
||
188 |
Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.
To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.
The function can be called with either null or an array for the parameter
$needle
but will only accept an array as$haystack
.