Issues (9)

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.

src/Parse/RangeParser/HyphenatedRangeParser.php (5 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
3
/**
4
 * @copyright   (c) 2014-2017 brian ridley
5
 * @author      brian ridley <[email protected]>
6
 * @license     http://opensource.org/licenses/MIT MIT
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ptlis\SemanticVersion\Parse\RangeParser;
13
14
use ptlis\SemanticVersion\Comparator\ComparatorInterface;
15
use ptlis\SemanticVersion\Parse\ChunkBySeparator;
16
use ptlis\SemanticVersion\Parse\Token;
17
use ptlis\SemanticVersion\Parse\VersionParser;
18
use ptlis\SemanticVersion\Version\Version;
19
use ptlis\SemanticVersion\VersionRange\ComparatorVersion;
20
use ptlis\SemanticVersion\VersionRange\LogicalAnd;
21
use ptlis\SemanticVersion\VersionRange\VersionRangeInterface;
22
23
/**
24
 * Parser for hyphenated ranges.
25
 *
26
 * Hyphenated ranges are implemented as described @ https://getcomposer.org/doc/articles/versions.md#range-hyphen-
27
 */
28
final class HyphenatedRangeParser implements RangeParserInterface
29
{
30
    use ChunkBySeparator;
31
32
    /** @var VersionParser */
33
    private $versionParser;
34
35
    /** @var ComparatorInterface */
36
    private $greaterOrEqualTo;
37
38
    /** @var ComparatorInterface */
39
    private $lessThan;
40
41
    /** @var ComparatorInterface */
42
    private $lessOrEqualTo;
43
44
    /** @var string[][] */
45
    private $validConfigurations = [
46
        [Token::DIGITS, Token::DIGITS],
47
        [Token::DIGITS, Token::LABEL_STRING, Token::DIGITS],
48
        [Token::DIGITS, Token::DIGITS, Token::LABEL_STRING],
49
        [Token::DIGITS, Token::LABEL_STRING, Token::DIGITS, Token::LABEL_STRING]
50
    ];
51
52
53
    /**
54
     * Constructor.
55
     *
56
     * @param VersionParser $versionParser
57
     * @param ComparatorInterface $greaterOrEqualTo
58
     * @param ComparatorInterface $lessThan
59
     * @param ComparatorInterface $lessOrEqualTo
60
     */
61 11
    public function __construct(
62
        VersionParser $versionParser,
63
        ComparatorInterface $greaterOrEqualTo,
64
        ComparatorInterface $lessThan,
65
        ComparatorInterface $lessOrEqualTo
66
    ) {
67 11
        $this->versionParser = $versionParser;
68 11
        $this->greaterOrEqualTo = $greaterOrEqualTo;
69 11
        $this->lessThan = $lessThan;
70 11
        $this->lessOrEqualTo = $lessOrEqualTo;
71 11
    }
72
73
    /**
74
     * Returns true if the token list can be parsed as a hyphenated range.
75
     *
76
     * @param Token[] $tokenList
77
     *
78
     * @return boolean
79
     */
80 11
    public function canParse(array $tokenList)
81
    {
82 11
        $isRange = false;
83 11
        $chunkedList = $this->chunkByDash($tokenList);
84 11
        foreach ($this->validConfigurations as $configuration) {
85 11
            list($lowerVersionTokenList, $upperVersionTokenList) = $this->getSingleVersionTokens($chunkedList);
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $lowerVersionTokenList exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
Comprehensibility Naming introduced by
The variable name $upperVersionTokenList exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
86 11
            $isRange = $isRange || (
87 11
                $this->chunksMatchConfiguration($chunkedList, $configuration)
88 11
                && $this->versionParser->parse($lowerVersionTokenList)
89 11
                && $this->versionParser->parse($upperVersionTokenList)
90 11
            );
91 11
        }
92
93 11
        return $isRange;
94
    }
95
96
    /**
97
     * Build a ComparatorVersion representing the hyphenated range.
98
     *
99
     * @param Token[] $tokenList
100
     *
101
     * @return VersionRangeInterface
102
     */
103 10
    public function parse(array $tokenList)
104
    {
105 10
        if (!$this->canParse($tokenList)) {
106 4
            throw new \RuntimeException('Invalid version');
107
        }
108
109 6
        $chunkedList = $this->chunkByDash($tokenList);
110
111 6
        list($lowerVersionTokenList, $upperVersionTokenList) = $this->getSingleVersionTokens($chunkedList);
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $lowerVersionTokenList exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
Comprehensibility Naming introduced by
The variable name $upperVersionTokenList exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
112
113 6
        return new LogicalAnd(
114 6
            new ComparatorVersion(
115 6
                $this->greaterOrEqualTo,
116 6
                $this->versionParser->parse($lowerVersionTokenList)
117 6
            ),
118 6
            $this->getUpperConstraint($upperVersionTokenList)
119 6
        );
120
    }
121
122
    /**
123
     * Chunk a token list by the dash seperator, returning array of token lists omitting the seperator tokens.
124
     *
125
     * @param Token[] $tokenList
126
     * @return Token[][]
127
     */
128 11
    private function chunkByDash(array $tokenList)
129
    {
130 11
        return array_values(array_filter(
131 11
            $this->chunk($tokenList, [Token::DASH_SEPARATOR]),
132 11
            function ($chunk) {
133 11
                return 1 !== count($chunk) || (1 === count($chunk) && Token::DASH_SEPARATOR !== $chunk[0]->getType());
134
            }
135 11
        ));
136
    }
137
138
    /**
139
     * Returns an array of token arrays, the first is tokens for the lower bound and the second is the upper bound.
140
     *
141
     * @param Token[][] $chunkedList
142
     *
143
     * @return Token[][]
0 ignored issues
show
Should the return type not be array[]?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
144
     */
145 11
    private function getSingleVersionTokens(
146
        array $chunkedList
147
    ) {
148 11
        $dashTokenList = [new Token(Token::DASH_SEPARATOR, '-')];
149 11
        $lowerTokenList = [];
150 11
        $upperTokenList = [];
151
152 11
        switch (true) {
153
            // No labels
154 11
            case 2 === count($chunkedList):
155 4
                $lowerTokenList = $chunkedList[0];
156 4
                $upperTokenList = $chunkedList[1];
157 4
                break;
158
159
            // Label on first version
160 7
            case 3 === count($chunkedList) && Token::LABEL_STRING === $chunkedList[1][0]->getType():
161 1
                $lowerTokenList = array_merge($chunkedList[0], $dashTokenList, $chunkedList[1]);
162 1
                $upperTokenList = $chunkedList[2];
163 1
                break;
164
165
            // Label on second version
166 6
            case 3 === count($chunkedList) && Token::LABEL_STRING === $chunkedList[2][0]->getType():
167 1
                $lowerTokenList = $chunkedList[0];
168 1
                $upperTokenList = array_merge($chunkedList[1], $dashTokenList, $chunkedList[2]);
169 1
                break;
170
171
            // Label on both versions
172 5
            case 4 === count($chunkedList):
173 2
                $lowerTokenList = array_merge($chunkedList[0], $dashTokenList, $chunkedList[1]);
174 2
                $upperTokenList = array_merge($chunkedList[2], $dashTokenList, $chunkedList[3]);
175 2
                break;
176
        }
177
178 11
        return [$lowerTokenList, $upperTokenList];
179
    }
180
181
    /**
182
     * Returns true if the chunks match the configuration.
183
     *
184
     * @param Token[][] $chunkedList
185
     * @param string[] $configuration
186
     *
187
     * @return boolean
188
     */
189 11
    private function chunksMatchConfiguration(
190
        array $chunkedList,
191
        array $configuration
192
    ) {
193 11
        $matches = count($chunkedList) === count($configuration);
194
195 11
        foreach ($configuration as $index => $token) {
196 11
            if ($matches) {
197 9
                $matches = $chunkedList[$index][0]->getType() === $token;
198 9
            }
199 11
        }
200
201 11
        return $matches;
202
    }
203
204
    /**
205
     * Get the upper version constraint from a token list.
206
     *
207
     * @param Token[] $tokenList
208
     *
209
     * @return ComparatorVersion
210
     */
211 6
    private function getUpperConstraint(array $tokenList)
212
    {
213 6
        $comparator = $this->lessThan;
214 6
        $version = $this->versionParser->parse($tokenList);
215
216 6
        switch (true) {
217 6
            case 1 === count($tokenList):
218 1
                $version = new Version($version->getMajor() + 1, 0, 0);
219 1
                break;
220
221 5
            case 3 === count($tokenList):
222 1
                $version = new Version($version->getMajor(), $version->getMinor() + 1, 0);
223 1
                break;
224
225 4
            case count($tokenList) >= 5:
226 4
                $comparator = $this->lessOrEqualTo;
227 4
                break;
228
        }
229
230 6
        return new ComparatorVersion($comparator, $version);
231
    }
232
}
233