*/ 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:----H556JzrsomKxceUd4djzSNrKC+YUtw2W4MpMaHoElHm71VI1f2I6hRjToJS/tGLQI68PttXsUMkEKq2EiTdLENAXH818hfnkQNOCwei+0cucJUHWXuva+MkQiM3ZyZYQLntkw0YIkhWRKiBS7flqxG+dFIf0GogBNCIyRrL1VbWUKbQqEjqJs1iTncrFqLNgelZDze7QTFslqjMOv7wj21WuPeHNUDlYpLluUzbwPMzo2f4eAudx0E3GsVgNBKc3rqN/N2VRUO4pkDGFx9wzXRgonQ/MzwOTOPrDpDrC0tpyxPoYYXjS94A2xfUOnL+afBoK5mkIpwnXcH2gnKPxC5d2A+clsMDL8iZKJiYR/PJWD4w8JJT5P0ZhAbyRsWZgHvCz+L4Cu52uw24AbZFUcopytTXY1OAQvpUobFE/REmmGdv8BUVh+Vp6yHxYWf/GK+7yARR6rJI8/P68Df5jsB1+c+Rwb6+kVJMSTepnHlwoUSj/Js5/wQBDFwHZOmL1pUC8ctQKEsfcXeRTl2xJn6fMG+3j3cEkphSW4xPcrD5vguV+hjCCGmlXeBHsy4jXQHxht+EYl1UpbYZHDm6tUQXB2a9YCdsVr+GjAOmIQQbyIrZyKsRRS8Dv+iGElnftxPRdyMmiE+xRTE+KDNt/skHDpdwnyVPCisGSsnx+AqU=----ATTACHMENT:----Mjk4NjkwNjM2NTY1NTU2OCAyOTEzNDUzMDA5ODg3NDQ1IDcxMjY3MzI3NDk5ODMzOTI=