Issues (1236)

Security Analysis    not enabled

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/psalm-language-server.php (6 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
require_once('command_functions.php');
3
4
use Psalm\Config;
5
use Psalm\Internal\Analyzer\ProjectAnalyzer;
6
use Psalm\Internal\IncludeCollector;
7
8
gc_disable();
9
10
// show all errors
11
error_reporting(-1);
12
13
require_once __DIR__ . '/Psalm/Internal/exception_handler.php';
14
15
$valid_short_options = [
16
    'h',
17
    'v',
18
    'c:',
19
    'r:',
20
];
21
22
$valid_long_options = [
23
    'clear-cache',
24
    'config:',
25
    'find-dead-code',
26
    'help',
27
    'root:',
28
    'use-ini-defaults',
29
    'version',
30
    'tcp:',
31
    'tcp-server',
32
    'disable-on-change::',
33
    'enable-autocomplete',
34
    'use-extended-diagnostic-codes',
35
    'verbose'
36
];
37
38
$args = array_slice($argv, 1);
39
40
$psalm_proxy = array_search('--language-server', $args, true);
41
42
if ($psalm_proxy !== false) {
43
    unset($args[$psalm_proxy]);
44
}
45
46
array_map(
47
    /**
48
     * @param string $arg
49
     *
50
     * @return void
51
     */
52
    function ($arg) use ($valid_long_options, $valid_short_options) {
53
        if (substr($arg, 0, 2) === '--' && $arg !== '--') {
54
            $arg_name = preg_replace('/=.*$/', '', substr($arg, 2));
55
56
            if (!in_array($arg_name, $valid_long_options, true)
57
                && !in_array($arg_name . ':', $valid_long_options, true)
58
                && !in_array($arg_name . '::', $valid_long_options, true)
59
            ) {
60
                fwrite(
61
                    STDERR,
62
                    'Unrecognised argument "--' . $arg_name . '"' . PHP_EOL
63
                    . 'Type --help to see a list of supported arguments' . PHP_EOL
64
                );
65
                error_log('Bad argument');
66
                exit(1);
67
            }
68
        } elseif (substr($arg, 0, 2) === '-' && $arg !== '-' && $arg !== '--') {
69
            $arg_name = preg_replace('/=.*$/', '', substr($arg, 1));
70
71
            if (!in_array($arg_name, $valid_short_options, true)
72
                && !in_array($arg_name . ':', $valid_short_options, true)
73
            ) {
74
                fwrite(
75
                    STDERR,
76
                    'Unrecognised argument "-' . $arg_name . '"' . PHP_EOL
77
                    . 'Type --help to see a list of supported arguments' . PHP_EOL
78
                );
79
                error_log('Bad argument');
80
                exit(1);
81
            }
82
        }
83
    },
84
    $args
85
);
86
87
// get options from command line
88
$options = getopt(implode('', $valid_short_options), $valid_long_options);
89
90 View Code Duplication
if (!array_key_exists('use-ini-defaults', $options)) {
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.

Loading history...
91
    ini_set('display_errors', '1');
92
    ini_set('display_startup_errors', '1');
93
    ini_set('memory_limit', (string) (4 * 1024 * 1024 * 1024));
94
}
95
96
if (array_key_exists('help', $options)) {
97
    $options['h'] = false;
98
}
99
100
if (array_key_exists('version', $options)) {
101
    $options['v'] = false;
102
}
103
104
if (isset($options['config'])) {
105
    $options['c'] = $options['config'];
106
}
107
108 View Code Duplication
if (isset($options['c']) && is_array($options['c'])) {
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.

Loading history...
109
    fwrite(STDERR, 'Too many config files provided' . PHP_EOL);
110
    exit(1);
111
}
112
113
if (array_key_exists('h', $options)) {
114
    echo <<<HELP
115
Usage:
116
    psalm-language-server [options]
117
118
Options:
119
    -h, --help
120
        Display this help message
121
122
    -v, --version
123
        Display the Psalm version
124
125
    -c, --config=psalm.xml
126
        Path to a psalm.xml configuration file. Run psalm --init to create one.
127
128
    -r, --root
129
        If running Psalm globally you'll need to specify a project root. Defaults to cwd
130
131
    --find-dead-code
132
        Look for dead code
133
134
    --clear-cache
135
        Clears all cache files that the language server uses for this specific project
136
137
    --use-ini-defaults
138
        Use PHP-provided ini defaults for memory and error display
139
140
    --tcp=url
141
        Use TCP mode (by default Psalm uses STDIO)
142
143
    --tcp-server
144
        Use TCP in server mode (default is client)
145
146
    --disable-on-change[=line-number-threshold]
147
        If added, the language server will not respond to onChange events.
148
        You can also specify a line count over which Psalm will not run on-change events.
149
150
    --enable-autocomplete[=BOOL]
151
        Enables or disables autocomplete on methods and properties. Default is true.
152
153
    --use-extended-diagnostic-codes
154
        Enables sending help uri links with the code in diagnostic messages.
155
156
    --verbose
157
        Will send log messages to the client with information.
158
HELP;
159
160
    exit;
161
}
162
163
if (array_key_exists('v', $options)) {
164
    echo 'Psalm ' . PSALM_VERSION . PHP_EOL;
165
    exit;
166
}
167
168 View Code Duplication
if (getcwd() === false) {
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.

Loading history...
169
    fwrite(STDERR, 'Cannot get current working directory' . PHP_EOL);
170
    exit(1);
171
}
172
173
if (isset($options['root'])) {
174
    $options['r'] = $options['root'];
175
}
176
177
$current_dir = (string)getcwd() . DIRECTORY_SEPARATOR;
178
179 View Code Duplication
if (isset($options['r']) && is_string($options['r'])) {
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.

Loading history...
180
    $root_path = realpath($options['r']);
181
182
    if (!$root_path) {
183
        fwrite(
184
            STDERR,
185
            'Could not locate root directory ' . $current_dir . DIRECTORY_SEPARATOR . $options['r'] . PHP_EOL
186
        );
187
        exit(1);
188
    }
189
190
    $current_dir = $root_path . DIRECTORY_SEPARATOR;
191
}
192
193
$vendor_dir = getVendorDir($current_dir);
194
195
require_once __DIR__ . '/Psalm/Internal/IncludeCollector.php';
196
$include_collector = new IncludeCollector();
197
198
$first_autoloader = $include_collector->runAndCollect(
199
    function () use ($current_dir, $options, $vendor_dir) {
200
        return requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);
201
    }
202
);
203
204
$ini_handler = new \Psalm\Internal\Fork\PsalmRestarter('PSALM');
205
206
$ini_handler->disableExtension('grpc');
207
208
// If Xdebug is enabled, restart without it
209
$ini_handler->check();
210
211
setlocale(LC_CTYPE, 'C');
212
213
$path_to_config = get_path_to_config($options);
214
215 View Code Duplication
if (isset($options['tcp'])) {
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.

Loading history...
216
    if (!is_string($options['tcp'])) {
217
        fwrite(STDERR, 'tcp url should be a string' . PHP_EOL);
218
        exit(1);
219
    }
220
}
221
222
$find_dead_code = isset($options['find-dead-code']);
223
224
$config = initialiseConfig($path_to_config, $current_dir, \Psalm\Report::TYPE_CONSOLE, $first_autoloader);
225
$config->setIncludeCollector($include_collector);
226
227
if ($config->resolve_from_config_file) {
228
    $current_dir = $config->base_dir;
229
    chdir($current_dir);
230
}
231
232
$config->setServerMode();
233
234 View Code Duplication
if (isset($options['clear-cache'])) {
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.

Loading history...
235
    $cache_directory = $config->getCacheDirectory();
236
237
    Config::removeCacheDirectory($cache_directory);
238
    echo 'Cache directory deleted' . PHP_EOL;
239
    exit;
240
}
241
242
$providers = new Psalm\Internal\Provider\Providers(
243
    new Psalm\Internal\Provider\FileProvider,
244
    new Psalm\Internal\Provider\ParserCacheProvider($config),
245
    new Psalm\Internal\Provider\FileStorageCacheProvider($config),
246
    new Psalm\Internal\Provider\ClassLikeStorageCacheProvider($config),
247
    new Psalm\Internal\Provider\FileReferenceCacheProvider($config),
248
    new Psalm\Internal\Provider\ProjectCacheProvider($current_dir . DIRECTORY_SEPARATOR . 'composer.lock')
249
);
250
251
$project_analyzer = new ProjectAnalyzer(
252
    $config,
253
    $providers
254
);
255
256
if (isset($options['disable-on-change'])) {
257
    $project_analyzer->onchange_line_limit = (int) $options['disable-on-change'];
258
}
259
260
$project_analyzer->provide_completion = !isset($options['enable-autocomplete'])
261
    || !is_string($options['enable-autocomplete'])
262
    || strtolower($options['enable-autocomplete']) !== 'false';
263
264
$config->visitComposerAutoloadFiles($project_analyzer);
265
266
if ($find_dead_code) {
267
    $project_analyzer->getCodebase()->reportUnusedCode();
268
}
269
270
if (isset($options['use-extended-diagnostic-codes'])) {
271
    $project_analyzer->language_server_use_extended_diagnostic_codes = true;
272
}
273
274
if (isset($options['verbose'])) {
275
    $project_analyzer->language_server_verbose = true;
276
}
277
278
$project_analyzer->server($options['tcp'] ?? null, isset($options['tcp-server']) ? true : false);
279