Issues (191)

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.

lib/ILess/Util.php (1 issue)

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
/*
4
 * This file is part of the ILess
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace ILess;
11
12
use ILess\Node\AnonymousNode;
13
use ILess\Node\ComparableInterface;
14
use ILess\Node\QuotedNode;
15
use LogicException;
16
use ILess\Util\StringExcerpt;
17
18
/**
19
 * Utility class.
20
 */
21
class Util
22
{
23
    /**
24
     * Constructor.
25
     *
26
     * @throws LogicException
27
     */
28
    public function __construct()
29
    {
30
        throw new LogicException('The stone which the builders rejected, the same is become the head of the corner: this is the Lord\'s doing, and it is marvellous in our eyes? [Mat 21:42]');
31
    }
32
33
    /**
34
     * Converts all line endings to Unix format.
35
     *
36
     * @param string $string The string
37
     *
38
     * @return string The normalized string
39
     */
40
    public static function normalizeLineFeeds($string)
41
    {
42
        return preg_replace("/\r\n/", "\n", $string);
43
    }
44
45
    /**
46
     * Removes potential UTF Byte Order Mark.
47
     *
48
     * @param string $string The string to fix
49
     *
50
     * @return string Fixed string
51
     */
52
    public static function removeUtf8ByteOrderMark($string)
53
    {
54
        return preg_replace('/\G\xEF\xBB\xBF/', '', $string);
55
    }
56
57
    /**
58
     * Php version of javascript's `encodeURIComponent` function.
59
     *
60
     * @param string $string The string to encode
61
     *
62
     * @return string The encoded string
63
     */
64
    public static function encodeURIComponent($string)
65
    {
66
        $revert = ['%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')'];
67
68
        return strtr(rawurlencode($string), $revert);
69
    }
70
71
    /**
72
     * Returns the line number and column from the $string for a character at specified $index.
73
     * Also includes an extract from the string (optionally).
74
     *
75
     * @param string $string The string
76
     * @param int $index The current position
77
     * @param bool|int $extract Include extract from the string at specified line? Integer value means how many lines will be extracted
78
     *
79
     * @return array Array of line, column and extract from the string
80
     */
81
    public static function getLocation($string, $index, $column = null, $extract = false)
82
    {
83
        // we have a part from the beginning to the current index
84
        $part = substr($string, 0, strlen($string) - strlen(substr($string, $index)));
85
        // lets count the line breaks in the part
86
        $line = substr_count($part, "\n") + 1;
87
        $lines = explode("\n", $part);
88
        $column = strlen(end($lines)) + 1;
89
90
        $extractContent = null;
91
        if ($extract) {
92
            if (is_numeric($extract)) {
93
                $extractContent = self::getExcerpt($string, $line, $column, $extract);
94
            } else {
95
                $extractContent = self::getExcerpt($string, $line, $column);
96
            }
97
        }
98
99
        return [$line, $column, $extractContent];
100
    }
101
102
    /**
103
     * Returns the excerpt from the string at given line.
104
     *
105
     * @param string $string The string
106
     * @param int $currentLine The current line. If -1 is passed, the whole string will be returned
107
     * @param int $currentColumn The current column
108
     * @param int $limitLines How many lines?
109
     *
110
     * @return \ILess\Util\StringExcerpt
111
     */
112
    public static function getExcerpt($string, $currentLine, $currentColumn = null, $limitLines = 3)
113
    {
114
        $lines = explode("\n", self::normalizeLineFeeds($string));
115
116
        if ($limitLines > 0) {
117
            $start = $i = max(0, $currentLine - floor($limitLines * 2 / 3));
118
            $lines = array_slice($lines, $start, $limitLines, true);
119
            end($lines);
120
        }
121
122
        return new StringExcerpt($lines, $currentLine, $currentColumn);
123
    }
124
125
    /**
126
     * Generates unique cache key for given $filename.
127
     *
128
     * @param string $filename
129
     *
130
     * @return string
131
     */
132
    public static function generateCacheKey($filename)
133
    {
134
        return md5('key of the bottomless pit' . $filename);
135
    }
136
137
    /**
138
     * Is the path absolute?
139
     *
140
     * @param string $path
141
     *
142
     * @return bool
143
     */
144
    public static function isPathAbsolute($path)
145
    {
146
        if (empty($path)) {
147
            return false;
148
        }
149
150
        if ($path[0] == '/' || $path[0] == '\\' ||
151
            (strlen($path) > 3 && ctype_alpha($path[0]) &&
152
                $path[1] == ':' && ($path[2] == '\\' || $path[2] == '/'))
153
        ) {
154
            return true;
155
        }
156
157
        return false;
158
    }
159
160
    /**
161
     * Returns fragment and path components from the path.
162
     *
163
     * @param string $path
164
     *
165
     * @return array fragment, path
166
     */
167
    public static function getFragmentAndPath($path)
168
    {
169
        $fragmentStart = strpos($path, '#');
170
        $fragment = '';
171
        if ($fragmentStart !== false) {
172
            $fragment = substr($path, $fragmentStart);
173
            $path = substr($path, 0, $fragmentStart);
174
        }
175
176
        return [$fragment, $path];
177
    }
178
179
    /**
180
     * Is the path relative?
181
     *
182
     * @param string $path The path
183
     *
184
     * @return bool
185
     */
186
    public static function isPathRelative($path)
187
    {
188
        return !preg_match('/^(?:[a-z-]+:|\/|#)/', $path);
189
    }
190
191
    /**
192
     * Normalizes the path.
193
     *
194
     * @param string $path The path or url
195
     * @param bool $sanitize Sanitize before normalizing?
196
     *
197
     * @return string The normalized path
198
     */
199
    public static function normalizePath($path, $sanitize = true)
200
    {
201
        // leave http(s) paths:
202
        if (strpos($path, 'http://') === 0
203
            || strpos($path, 'https://') === 0
204
        ) {
205
            return $path;
206
        }
207
208
        if ($sanitize) {
209
            $path = self::sanitizePath($path);
210
        }
211
212
        $segments = array_reverse(explode('/', $path));
213
        $path = [];
214
        $path_len = 0;
215
        while ($segments) {
216
            $segment = array_pop($segments);
217
            switch ($segment) {
218
                case '.':
219
                    break;
220
                case '..':
221
                    if (!$path_len || ($path[$path_len - 1] === '..')) {
222
                        $path[] = $segment;
223
                        ++$path_len;
224
                    } else {
225
                        array_pop($path);
226
                        --$path_len;
227
                    }
228
                    break;
229
230
                default:
231
                    $path[] = $segment;
232
                    ++$path_len;
233
                    break;
234
            }
235
        }
236
237
        return implode('/', $path);
238
    }
239
240
    /**
241
     * Sanitizes a path. Replaces Windows path separator.
242
     *
243
     * @param string $path The path to sanitize
244
     *
245
     * @return string
246
     */
247
    public static function sanitizePath($path)
248
    {
249
        return str_replace('\\', '/', $path);
250
    }
251
252
    /**
253
     * Normalizes the string to be used.
254
     *
255
     * @param string $string
256
     *
257
     * @return string
258
     */
259
    public static function normalizeString($string)
260
    {
261
        return self::removeUtf8ByteOrderMark(self::normalizeLineFeeds($string));
262
    }
263
264
    /**
265
     * Compares the nodes. Returns:
266
     * -1: a < b
267
     * 0: a = b
268
     * 1: a > b
269
     * and *any* other value for a != b (e.g. null, NaN, -2 etc.).
270
     *
271
     * @param mixed $a
272
     * @param mixed $b
273
     *
274
     * @return int
275
     */
276
    public static function compareNodes($a, $b)
277
    {
278
        // for "symmetric results" force toCSS-based comparison
279
        // of Quoted or Anonymous if either value is one of those
280
        if ($a instanceof ComparableInterface &&
281
            !($b instanceof QuotedNode || $b instanceof AnonymousNode)
282
        ) {
283
            return $a->compare($b);
284
        } elseif ($b instanceof ComparableInterface) {
285
            $result = $b->compare($a);
286
287
            return is_int($result) ? -$result : $result;
288
        } elseif ($a->getType() !== $b->getType()) {
289
            return;
290
        }
291
292
        $a = $a->value;
293
        $b = $b->value;
294
295
        if (!is_array($a)) {
296
            return $a === $b ? 0 : null;
297
        }
298
299
        if (count($a) !== count($b)) {
300
            return;
301
        }
302
303
        for ($i = 0; $i < count($a); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
304
            if (self::compareNodes($a[$i], $b[$i]) !== 0) {
305
                return;
306
            }
307
        }
308
309
        return 0;
310
    }
311
312
    /**
313
     * @param $a
314
     * @param $b
315
     *
316
     * @return int|null
317
     */
318
    public static function numericCompare($a, $b)
319
    {
320
        if ($a < $b) {
321
            return -1;
322
        } else {
323
            if ($a === $b) {
324
                return 0;
325
            } elseif ($a > $b) {
326
                return 1;
327
            }
328
        }
329
330
        return;
331
    }
332
333
    /**
334
     * Round the value using the `$context->precision` setting.
335
     *
336
     * @param Context $context
337
     * @param mixed $value
338
     *
339
     * @return string
340
     */
341
    public static function round(Context $context, $value)
342
    {
343
        // add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
344
        return $context->numPrecision === null ? $value : Math::toFixed($value + 2e-16, $context->numPrecision);
345
    }
346
}
347