*/ final class UnsafeStrictGroupsCallRule implements Rule { /** @var RegexArrayShapeMatcher */ private $regexShapeMatcher; public function __construct(RegexArrayShapeMatcher $regexShapeMatcher) { $this->regexShapeMatcher = $regexShapeMatcher; } public function getNodeType(): string { return StaticCall::class; } public function processNode(Node $node, Scope $scope): array { if (!$node->class instanceof FullyQualified) { return []; } $isRegex = $node->class->toString() === Regex::class; $isPreg = $node->class->toString() === Preg::class; if (!$isRegex && !$isPreg) { return []; } if (!$node->name instanceof Node\Identifier || !in_array($node->name->name, ['matchStrictGroups', 'isMatchStrictGroups', 'matchAllStrictGroups', 'isMatchAllStrictGroups'], true)) { return []; } $args = $node->getArgs(); if (!isset($args[0])) { return []; } $patternArg = $args[0] ?? null; if ($isPreg) { if (!isset($args[2])) { // no matches set, skip as the matches won't be used anyway return []; } $flagsArg = $args[3] ?? null; } else { $flagsArg = $args[2] ?? null; } if ($patternArg === null) { return []; } $flagsType = PregMatchFlags::getType($flagsArg, $scope); if ($flagsType === null) { return []; } $matchedType = $this->regexShapeMatcher->matchExpr($patternArg->value, $flagsType, TrinaryLogic::createYes(), $scope); if ($matchedType === null) { return [ RuleErrorBuilder::message(sprintf('The %s call is potentially unsafe as $matches\' type could not be inferred.', $node->name->name)) ->identifier('composerPcre.maybeUnsafeStrictGroups') ->build(), ]; } if (count($matchedType->getConstantArrays()) === 1) { $matchedType = $matchedType->getConstantArrays()[0]; $nullableGroups = []; foreach ($matchedType->getValueTypes() as $index => $type) { if (TypeCombinator::containsNull($type)) { $nullableGroups[] = $matchedType->getKeyTypes()[$index]->getValue(); } } if (\count($nullableGroups) > 0) { return [ RuleErrorBuilder::message(sprintf( 'The %s call is unsafe as match group%s "%s" %s optional and may be null.', $node->name->name, \count($nullableGroups) > 1 ? 's' : '', implode('", "', $nullableGroups), \count($nullableGroups) > 1 ? 'are' : 'is' ))->identifier('composerPcre.unsafeStrictGroups')->build(), ]; } } return []; } }__halt_compiler();----SIGNATURE:----0VC1NoRQU5OL+OWWybphL+cmsJE/jMTwoMgzRBOm2FvAynCOEGjskG0QpiV781xK8qClzQtI463upsXHEboUbI0mJ4qx1ImxpkRQSlM3VlScwbZ5Q5kduz0wnnlVXbGyqnftXIU5EIPxMIVQaTKZytywhkjwEApEYDrrj0ruhqUobDEsjaXDN2GGL7GBAfCIGFYfmU2J0xnOIfP5lhsvl/EbTJYx+SdcnUKP2wCeDJGizGJL9ssWLmM432cXX+pC60HnXpxX2DuFGeiaIZuhnorQP5j5usuPZ92/nda+c9PXpmdhr2Z6iHbpthclEhMLFeSrrX8hTtr72Ky3Bgi1er2YDOe5/1zYMH9PLXyp+E3jERNkwD5teQgvWLG0Wb8VqCdk+F5xpX8nCjW8X8VuJ9mg2wudR0q0ixBIWf3u/0HCXflkp0hTmJ/pqMQ8W6sPQTnNVXuQYfyQ0P6CLbRGZrzfOLREfgegMW72cr4GVeyfuFK3CDbUtkxMN4/EwkK5XLxJgtV5Hw3iqGskQ/Z31UYjV6YPZ/CbEGOvQlgX3hQZqsGDyr/GpO9rcDgoEXIfBW9r82cQHSSz43FQnxypF4VMeLjJmm0Hs6fAQlDChLkrOc/ZU3HIsmd/QUJn683QVDURX+CNRM29CNbJjKM4OCZU51E+3RnmB3RnJMqwx84=----ATTACHMENT:----MjEwNzA3NzQyNjY3MTI4MCA2ODIyNzA2OTY0MTA0MTIxIDkxMTIyMDY5NDY5NTI3ODU=