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 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Lamoda\GS1Parser\Parser; |
||
| 6 | |||
| 7 | use Lamoda\GS1Parser\Barcode; |
||
| 8 | use Lamoda\GS1Parser\Exception\InvalidBarcodeException; |
||
| 9 | |||
| 10 | /** |
||
| 11 | * Performs barcode parsing according to |
||
| 12 | * https://www.gs1.org/sites/default/files/docs/barcodes/GS1_General_Specifications.pdf |
||
| 13 | */ |
||
| 14 | final class Parser implements ParserInterface |
||
| 15 | { |
||
| 16 | private const ENCODABLE_VALUE_CHARACTERS_SET = [ |
||
| 17 | '!', |
||
| 18 | '"', |
||
| 19 | '%', |
||
| 20 | '&', |
||
| 21 | '\'', |
||
| 22 | '(', |
||
| 23 | ')', |
||
| 24 | '*', |
||
| 25 | '+', |
||
| 26 | ',', |
||
| 27 | '-', |
||
| 28 | '_', |
||
| 29 | '.', |
||
| 30 | '/', |
||
| 31 | '0', |
||
| 32 | '1', |
||
| 33 | '2', |
||
| 34 | '3', |
||
| 35 | '4', |
||
| 36 | '5', |
||
| 37 | '6', |
||
| 38 | '7', |
||
| 39 | '8', |
||
| 40 | '9', |
||
| 41 | ':', |
||
| 42 | ';', |
||
| 43 | '<', |
||
| 44 | '=', |
||
| 45 | '>', |
||
| 46 | '?', |
||
| 47 | 'A', |
||
| 48 | 'B', |
||
| 49 | 'C', |
||
| 50 | 'D', |
||
| 51 | 'E', |
||
| 52 | 'F', |
||
| 53 | 'G', |
||
| 54 | 'H', |
||
| 55 | 'I', |
||
| 56 | 'J', |
||
| 57 | 'K', |
||
| 58 | 'L', |
||
| 59 | 'M', |
||
| 60 | 'N', |
||
| 61 | 'O', |
||
| 62 | 'P', |
||
| 63 | 'Q', |
||
| 64 | 'R', |
||
| 65 | 'S', |
||
| 66 | 'T', |
||
| 67 | 'U', |
||
| 68 | 'V', |
||
| 69 | 'W', |
||
| 70 | 'X', |
||
| 71 | 'Y', |
||
| 72 | 'Z', |
||
| 73 | 'a', |
||
| 74 | 'b', |
||
| 75 | 'c', |
||
| 76 | 'd', |
||
| 77 | 'e', |
||
| 78 | 'f', |
||
| 79 | 'g', |
||
| 80 | 'h', |
||
| 81 | 'i', |
||
| 82 | 'j', |
||
| 83 | 'k', |
||
| 84 | 'l', |
||
| 85 | 'm', |
||
| 86 | 'n', |
||
| 87 | 'o', |
||
| 88 | 'p', |
||
| 89 | 'q', |
||
| 90 | 'r', |
||
| 91 | 's', |
||
| 92 | 't', |
||
| 93 | 'u', |
||
| 94 | 'v', |
||
| 95 | 'w', |
||
| 96 | 'x', |
||
| 97 | 'y', |
||
| 98 | 'z', |
||
| 99 | ]; |
||
| 100 | private const FIXED_LENGTH_AIS = [ |
||
| 101 | '00' => 20, |
||
| 102 | '01' => 16, |
||
| 103 | '02' => 16, |
||
| 104 | '03' => 16, |
||
| 105 | '04' => 18, |
||
| 106 | '11' => 8, |
||
| 107 | '12' => 8, |
||
| 108 | '13' => 8, |
||
| 109 | '14' => 8, |
||
| 110 | '15' => 8, |
||
| 111 | '16' => 8, |
||
| 112 | '17' => 8, |
||
| 113 | '18' => 8, |
||
| 114 | '19' => 8, |
||
| 115 | '20' => 4, |
||
| 116 | '31' => 10, |
||
| 117 | '32' => 10, |
||
| 118 | '33' => 10, |
||
| 119 | '34' => 10, |
||
| 120 | '35' => 10, |
||
| 121 | '36' => 10, |
||
| 122 | '41' => 16, |
||
| 123 | ]; |
||
| 124 | private const FIXED_AI_LENGTH = 2; |
||
| 125 | |||
| 126 | /** |
||
| 127 | * @var ParserConfig |
||
| 128 | */ |
||
| 129 | private $config; |
||
| 130 | |||
| 131 | 18 | public function __construct(ParserConfig $config) |
|
| 132 | { |
||
| 133 | 18 | $this->config = $config; |
|
| 134 | 18 | } |
|
| 135 | |||
| 136 | 18 | public function parse(string $data): Barcode |
|
| 137 | { |
||
| 138 | 18 | $data = trim($data); |
|
| 139 | |||
| 140 | 18 | if ($data === '') { |
|
| 141 | 1 | throw InvalidBarcodeException::becauseBarcodeIsEmpty(); |
|
| 142 | } |
||
| 143 | |||
| 144 | 17 | [$fnc1Prefix, $codeType] = $this->fetchFNC1Prefix($data); |
|
| 145 | |||
| 146 | 17 | if ($fnc1Prefix === null && $this->config->isFnc1SequenceRequired()) { |
|
| 147 | 1 | throw InvalidBarcodeException::becauseFNC1SequenceIsNotFound(); |
|
| 148 | } |
||
| 149 | |||
| 150 | 16 | $codeOffset = strlen((string)$fnc1Prefix); |
|
| 151 | 16 | $dataLength = strlen($data); |
|
| 152 | |||
| 153 | 16 | if ($dataLength <= $codeOffset) { |
|
| 154 | 1 | throw InvalidBarcodeException::becauseNoDataPresent(); |
|
| 155 | } |
||
| 156 | |||
| 157 | 15 | $position = $codeOffset; |
|
| 158 | 15 | $foundAIs = []; |
|
| 159 | 15 | $buffer = []; |
|
| 160 | 15 | while ($position < $dataLength) { |
|
| 161 | 15 | [$ai, $length] = $this->fetchFixedAI($data, $position, $dataLength); |
|
| 162 | 15 | $value = null; |
|
|
0 ignored issues
–
show
|
|||
| 163 | |||
| 164 | 15 | if ($ai !== null) { |
|
| 165 | 14 | if ($position + $length > $dataLength) { |
|
| 166 | 1 | throw InvalidBarcodeException::becauseNotEnoughDataFoAI( |
|
| 167 | 1 | $ai, |
|
| 168 | 1 | $length, |
|
| 169 | 1 | $dataLength - $position |
|
| 170 | ); |
||
| 171 | } |
||
| 172 | |||
| 173 | 13 | $isKnownAI = in_array($ai, $this->config->getKnownAIs(), true); |
|
| 174 | |||
| 175 | 13 | if ($isKnownAI) { |
|
| 176 | 3 | $value = substr($data, $position + self::FIXED_AI_LENGTH, $length - self::FIXED_AI_LENGTH); |
|
| 177 | } else { |
||
| 178 | 10 | $ai = null; |
|
| 179 | 10 | $value = substr($data, $position, $length); |
|
| 180 | } |
||
| 181 | |||
| 182 | 13 | if (strpos($value, $this->config->getGroupSeparator()) !== false) { |
|
| 183 | 1 | throw InvalidBarcodeException::becauseGroupSeparatorWasNotExpected($value); |
|
| 184 | } |
||
| 185 | |||
| 186 | 12 | $position += $length; |
|
| 187 | } else { |
||
| 188 | 12 | [$ai, $aiLength] = $this->fetchKnownAI($data, $position); |
|
| 189 | |||
| 190 | 12 | $groupSeparatorPosition = strpos($data, $this->config->getGroupSeparator(), $position); |
|
| 191 | 12 | if ($groupSeparatorPosition !== false) { |
|
| 192 | 6 | $length = $groupSeparatorPosition - $position; |
|
| 193 | } else { |
||
| 194 | 9 | $length = $dataLength - $position; |
|
| 195 | } |
||
| 196 | |||
| 197 | 12 | if ($ai) { |
|
| 198 | 3 | $value = substr($data, $position + $aiLength, $length - $aiLength); |
|
| 199 | } else { |
||
| 200 | 9 | $value = substr($data, $position, $length); |
|
| 201 | } |
||
| 202 | |||
| 203 | 12 | $position += $length + strlen($this->config->getGroupSeparator()); |
|
| 204 | } |
||
| 205 | |||
| 206 | 13 | $this->assertValueIsValid($value); |
|
| 207 | |||
| 208 | 12 | if ($ai) { |
|
| 209 | 3 | $foundAIs[$ai] = $value; |
|
| 210 | } else { |
||
| 211 | 9 | $buffer[] = $value; |
|
| 212 | } |
||
| 213 | } |
||
| 214 | |||
| 215 | 12 | return new Barcode($data, $codeType, $foundAIs, $buffer, (string)$fnc1Prefix); |
|
| 216 | } |
||
| 217 | |||
| 218 | 17 | private function fetchFNC1Prefix(string $data): array |
|
| 219 | { |
||
| 220 | 17 | foreach ($this->config->getFnc1PrefixMap() as $prefix => $codeType) { |
|
| 221 | 17 | if (substr_compare($data, $prefix, 0, strlen($prefix), true) === 0) { |
|
| 222 | 17 | return [$prefix, $codeType]; |
|
| 223 | } |
||
| 224 | } |
||
| 225 | |||
| 226 | 5 | return [null, Barcode::TYPE_UNKNOWN]; |
|
| 227 | } |
||
| 228 | |||
| 229 | 15 | private function fetchFixedAI(string $data, int $position, int $dataLength): array |
|
| 230 | { |
||
| 231 | 15 | if ($dataLength - $position < self::FIXED_AI_LENGTH) { |
|
| 232 | 1 | return [null, null]; |
|
| 233 | } |
||
| 234 | |||
| 235 | 14 | $ai = substr($data, $position, self::FIXED_AI_LENGTH); |
|
| 236 | |||
| 237 | 14 | $length = self::FIXED_LENGTH_AIS[$ai] ?? null; |
|
| 238 | |||
| 239 | 14 | if ($length === null) { |
|
| 240 | 11 | return [null, null]; |
|
| 241 | } |
||
| 242 | |||
| 243 | 14 | return [$ai, $length]; |
|
| 244 | } |
||
| 245 | |||
| 246 | 12 | private function fetchKnownAI(string $data, int $position): array |
|
| 247 | { |
||
| 248 | 12 | foreach ($this->config->getKnownAIs() as $ai) { |
|
| 249 | 3 | $aiLength = strlen($ai); |
|
| 250 | 3 | if (substr_compare($data, $ai, $position, $aiLength, true) === 0) { |
|
| 251 | 3 | return [substr($data, $position, $aiLength), $aiLength]; |
|
| 252 | } |
||
| 253 | } |
||
| 254 | |||
| 255 | 9 | return [null, null]; |
|
| 256 | } |
||
| 257 | |||
| 258 | 13 | private function assertValueIsValid(string $value): void |
|
| 259 | { |
||
| 260 | 13 | $unencodableCharacters = array_diff(str_split($value), self::ENCODABLE_VALUE_CHARACTERS_SET); |
|
| 261 | |||
| 262 | 13 | if (count($unencodableCharacters) > 0) { |
|
| 263 | 1 | throw InvalidBarcodeException::becauseValueContainsInvalidCharacters(...$unencodableCharacters); |
|
| 264 | } |
||
| 265 | 12 | } |
|
| 266 | } |
||
| 267 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVarassignment in line 1 and the$higherassignment in line 2 are dead. The first because$myVaris never used and the second because$higheris always overwritten for every possible time line.