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 | namespace Spatie\SlashCommand\Handlers; |
||
4 | |||
5 | use Illuminate\Console\Parser; |
||
6 | use Illuminate\Support\Str; |
||
7 | use Spatie\SlashCommand\Exceptions\InvalidHandler; |
||
8 | use Spatie\SlashCommand\Exceptions\InvalidInput; |
||
9 | use Spatie\SlashCommand\Request; |
||
10 | use Symfony\Component\Console\Command\Command; |
||
11 | use Symfony\Component\Console\Exception\RuntimeException; |
||
12 | use Symfony\Component\Console\Helper\DescriptorHelper; |
||
13 | use Symfony\Component\Console\Input\InputDefinition; |
||
14 | use Symfony\Component\Console\Input\StringInput; |
||
15 | use Symfony\Component\Console\Output\BufferedOutput; |
||
16 | |||
17 | abstract class SignatureHandler extends BaseHandler |
||
18 | { |
||
19 | /** @var string */ |
||
20 | protected $name; |
||
21 | |||
22 | /** @var string */ |
||
23 | protected $signature; |
||
24 | |||
25 | /** @var string */ |
||
26 | protected $description; |
||
27 | |||
28 | /** @var \Symfony\Component\Console\Input\StringInput */ |
||
29 | protected $input; |
||
30 | |||
31 | /** @var \Symfony\Component\Console\Input\InputDefinition */ |
||
32 | protected $inputDefinition; |
||
33 | |||
34 | /** @var bool */ |
||
35 | protected $signatureIsBound; |
||
36 | |||
37 | public function __construct(Request $request) |
||
38 | { |
||
39 | parent::__construct($request); |
||
40 | |||
41 | if (empty($this->signature)) { |
||
42 | throw InvalidHandler::signatureIsRequired(static::class); |
||
43 | } |
||
44 | |||
45 | $this->signatureIsBound = $this->bindSignature($this->signature); |
||
0 ignored issues
–
show
|
|||
46 | } |
||
47 | |||
48 | public function getName(): string |
||
49 | { |
||
50 | return $this->name; |
||
51 | } |
||
52 | |||
53 | public function getSignature(): string |
||
54 | { |
||
55 | return $this->signature; |
||
56 | } |
||
57 | |||
58 | public function getDescription(): string |
||
59 | { |
||
60 | return $this->description ?: ''; |
||
61 | } |
||
62 | |||
63 | /** |
||
64 | * @param string $foo |
||
65 | */ |
||
66 | public function getArgument($foo) |
||
67 | { |
||
68 | return $this->input->getArgument($foo); |
||
69 | } |
||
70 | |||
71 | public function getOption($foo) |
||
72 | { |
||
73 | return $this->input->getOption($foo); |
||
74 | } |
||
75 | |||
76 | public function getArguments(): array |
||
77 | { |
||
78 | return $this->input->getArguments(); |
||
79 | } |
||
80 | |||
81 | public function getOptions(): array |
||
82 | { |
||
83 | return $this->input->getOptions(); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Get the full command (eg. `/bot ping`). |
||
88 | * |
||
89 | * @return string |
||
90 | */ |
||
91 | public function getFullCommand(): string |
||
92 | { |
||
93 | return "/{$this->request->command} {$this->name}"; |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * Get the usage description, including parameters and options. |
||
98 | * |
||
99 | * @return string |
||
100 | */ |
||
101 | public function getHelpDescription(): string |
||
102 | { |
||
103 | $inputDefinition = $this->inputDefinition; |
||
104 | $output = new BufferedOutput(); |
||
105 | |||
106 | $name = $this->getFullCommand(); |
||
107 | |||
108 | $command = (new Command($name)) |
||
109 | ->setDefinition($inputDefinition) |
||
110 | ->setDescription($this->getDescription()); |
||
111 | |||
112 | $descriptor = new DescriptorHelper(); |
||
113 | $descriptor->describe($output, $command); |
||
114 | |||
115 | return $output->fetch(); |
||
116 | } |
||
117 | |||
118 | public function canHandle(Request $request): bool |
||
119 | { |
||
120 | if (! $this->signatureIsBound) { |
||
121 | return false; |
||
122 | } |
||
123 | |||
124 | $signatureParts = new SignatureParts($this->signature); |
||
125 | |||
126 | if (! Str::is($signatureParts->getSlashCommandName(), $request->command)) { |
||
127 | return false; |
||
128 | } |
||
129 | |||
130 | if (explode(' ', $request->text)[0] != $signatureParts->getHandlerName()) { |
||
131 | return false; |
||
132 | } |
||
133 | |||
134 | return true; |
||
135 | } |
||
136 | |||
137 | protected function bindSignature() |
||
138 | { |
||
139 | $signatureParts = new SignatureParts($this->signature); |
||
140 | |||
141 | $signature = $signatureParts->getSignatureWithoutCommandName(); |
||
142 | |||
143 | [$name, $arguments, $options] = Parser::parse($signature); |
||
0 ignored issues
–
show
|
|||
144 | |||
145 | $this->name = $name; |
||
146 | |||
147 | $inputDefinition = new InputDefinition(); |
||
148 | |||
149 | foreach ($arguments as $argument) { |
||
150 | $inputDefinition->addArgument($argument); |
||
151 | } |
||
152 | |||
153 | foreach ($options as $option) { |
||
154 | $inputDefinition->addOption($option); |
||
155 | } |
||
156 | |||
157 | $inputWithoutHandlerName = explode(' ', $this->request->text, 2)[1] ?? ''; |
||
158 | |||
159 | $this->input = new StringInput($inputWithoutHandlerName); |
||
160 | $this->inputDefinition = $inputDefinition; |
||
161 | |||
162 | try { |
||
163 | $this->input->bind($inputDefinition); |
||
164 | } catch (RuntimeException $exception) { |
||
165 | return false; |
||
166 | } |
||
167 | |||
168 | return true; |
||
169 | } |
||
170 | |||
171 | public function validate() |
||
172 | { |
||
173 | try { |
||
174 | $this->input->validate(); |
||
175 | } catch (RuntimeException $exception) { |
||
176 | throw new InvalidInput($exception->getMessage(), $this, $exception); |
||
177 | } |
||
178 | } |
||
179 | } |
||
180 |
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
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.