> */ private array $after_method_checks = []; /** * Static methods to be called after project function checks have completed * * Called after function calls to functions defined in the project. * * Allows influencing the return type and adding of modifications. * * @var list> */ public array $after_function_checks = []; /** * Static methods to be called after every function call * * Called after each function call, including php internal functions. * * Cannot change the call or influence its return type * * @var list> */ public array $after_every_function_checks = []; /** * Static methods to be called before expression checks are completed * * @var list> */ public array $before_expression_checks = []; /** * Static methods to be called after expression checks have completed * * @var list> */ public array $after_expression_checks = []; /** * Static methods to be called before statement checks are processed * * @var list> */ public array $before_statement_checks = []; /** * Static methods to be called after statement checks have completed * * @var list> */ public array $after_statement_checks = []; /** * Static methods to be called after method checks have completed * * @var list> */ public array $string_interpreters = []; /** * Static methods to be called after classlike exists checks have completed * * @var list> */ public array $after_classlike_exists_checks = []; /** * Static methods to be called after classlike checks have completed * * @var list> */ public array $after_classlike_checks = []; /** * Static methods to be called after classlikes have been scanned * * @var list> */ private array $after_visit_classlikes = []; /** * Static methods to be called after codebase has been populated * * @var list> */ public array $after_codebase_populated = []; /** * @var list> */ private array $before_add_issue = []; /** * Static methods to be called after codebase has been populated * * @var list> */ public array $after_analysis = []; /** * Static methods to be called after a file has been analyzed * * @var list> */ public array $after_file_checks = []; /** * Static methods to be called before a file is analyzed * * @var list> */ public array $before_file_checks = []; /** * Static methods to be called after functionlike checks have completed * * @var list> */ public array $after_functionlike_checks = []; /** * Static methods to be called to see if taints should be added * * @var list> */ public array $add_taints_checks = []; /** * Static methods to be called to see if taints should be removed * * @var list> */ public array $remove_taints_checks = []; /** * @param class-string $class */ public function registerClass(string $class): void { if (is_subclass_of($class, AfterMethodCallAnalysisInterface::class)) { $this->after_method_checks[] = $class; } if (is_subclass_of($class, AfterFunctionCallAnalysisInterface::class)) { $this->after_function_checks[] = $class; } if (is_subclass_of($class, AfterEveryFunctionCallAnalysisInterface::class)) { $this->after_every_function_checks[] = $class; } if (is_subclass_of($class, BeforeExpressionAnalysisInterface::class)) { $this->before_expression_checks[] = $class; } if (is_subclass_of($class, AfterExpressionAnalysisInterface::class)) { $this->after_expression_checks[] = $class; } if (is_subclass_of($class, BeforeStatementAnalysisInterface::class)) { $this->before_statement_checks[] = $class; } if (is_subclass_of($class, AfterStatementAnalysisInterface::class)) { $this->after_statement_checks[] = $class; } if (is_subclass_of($class, StringInterpreterInterface::class)) { $this->string_interpreters[] = $class; } if (is_subclass_of($class, AfterClassLikeExistenceCheckInterface::class)) { $this->after_classlike_exists_checks[] = $class; } if (is_subclass_of($class, AfterClassLikeAnalysisInterface::class)) { $this->after_classlike_checks[] = $class; } if (is_subclass_of($class, AfterClassLikeVisitInterface::class)) { $this->after_visit_classlikes[] = $class; } if (is_subclass_of($class, AfterCodebasePopulatedInterface::class)) { $this->after_codebase_populated[] = $class; } if (is_subclass_of($class, BeforeAddIssueInterface::class)) { $this->before_add_issue[] = $class; } if (is_subclass_of($class, AfterAnalysisInterface::class)) { $this->after_analysis[] = $class; } if (is_subclass_of($class, AfterFileAnalysisInterface::class)) { $this->after_file_checks[] = $class; } if (is_subclass_of($class, BeforeFileAnalysisInterface::class)) { $this->before_file_checks[] = $class; } if (is_subclass_of($class, AfterFunctionLikeAnalysisInterface::class)) { $this->after_functionlike_checks[] = $class; } if (is_subclass_of($class, AddTaintsInterface::class)) { $this->add_taints_checks[] = $class; } if (is_subclass_of($class, RemoveTaintsInterface::class)) { $this->remove_taints_checks[] = $class; } } public function hasAfterMethodCallAnalysisHandlers(): bool { return count($this->after_method_checks) > 0; } public function dispatchAfterMethodCallAnalysis(AfterMethodCallAnalysisEvent $event): void { foreach ($this->after_method_checks as $handler) { $handler::afterMethodCallAnalysis($event); } } public function dispatchAfterFunctionCallAnalysis(AfterFunctionCallAnalysisEvent $event): void { foreach ($this->after_function_checks as $handler) { $handler::afterFunctionCallAnalysis($event); } } public function dispatchAfterEveryFunctionCallAnalysis(AfterEveryFunctionCallAnalysisEvent $event): void { foreach ($this->after_every_function_checks as $handler) { $handler::afterEveryFunctionCallAnalysis($event); } } public function dispatchBeforeExpressionAnalysis(BeforeExpressionAnalysisEvent $event): ?bool { foreach ($this->before_expression_checks as $handler) { if ($handler::beforeExpressionAnalysis($event) === false) { return false; } } return null; } public function dispatchAfterExpressionAnalysis(AfterExpressionAnalysisEvent $event): ?bool { foreach ($this->after_expression_checks as $handler) { if ($handler::afterExpressionAnalysis($event) === false) { return false; } } return null; } public function dispatchBeforeStatementAnalysis(BeforeStatementAnalysisEvent $event): ?bool { foreach ($this->before_statement_checks as $handler) { if ($handler::beforeStatementAnalysis($event) === false) { return false; } } return null; } public function dispatchAfterStatementAnalysis(AfterStatementAnalysisEvent $event): ?bool { foreach ($this->after_statement_checks as $handler) { if ($handler::afterStatementAnalysis($event) === false) { return false; } } return null; } public function dispatchStringInterpreter(StringInterpreterEvent $event): ?TLiteralString { foreach ($this->string_interpreters as $handler) { if ($type = $handler::getTypeFromValue($event)) { return $type; } } return null; } public function dispatchAfterClassLikeExistenceCheck(AfterClassLikeExistenceCheckEvent $event): void { foreach ($this->after_classlike_exists_checks as $handler) { $handler::afterClassLikeExistenceCheck($event); } } public function dispatchAfterClassLikeAnalysis(AfterClassLikeAnalysisEvent $event): ?bool { foreach ($this->after_classlike_checks as $handler) { if ($handler::afterStatementAnalysis($event) === false) { return false; } } return null; } public function hasAfterClassLikeVisitHandlers(): bool { return count($this->after_visit_classlikes) > 0; } public function dispatchAfterClassLikeVisit(AfterClassLikeVisitEvent $event): void { foreach ($this->after_visit_classlikes as $handler) { $handler::afterClassLikeVisit($event); } } public function dispatchAfterCodebasePopulated(AfterCodebasePopulatedEvent $event): void { foreach ($this->after_codebase_populated as $handler) { $handler::afterCodebasePopulated($event); } } public function dispatchBeforeAddIssue(BeforeAddIssueEvent $event): ?bool { foreach ($this->before_add_issue as $handler) { $result = $handler::beforeAddIssue($event); if (is_bool($result)) { return $result; } } return null; } public function dispatchAfterAnalysis(AfterAnalysisEvent $event): void { foreach ($this->after_analysis as $handler) { $handler::afterAnalysis($event); } } public function dispatchAfterFileAnalysis(AfterFileAnalysisEvent $event): void { foreach ($this->after_file_checks as $handler) { $handler::afterAnalyzeFile($event); } } public function dispatchBeforeFileAnalysis(BeforeFileAnalysisEvent $event): void { foreach ($this->before_file_checks as $handler) { $handler::beforeAnalyzeFile($event); } } public function dispatchAfterFunctionLikeAnalysis(AfterFunctionLikeAnalysisEvent $event): ?bool { foreach ($this->after_functionlike_checks as $handler) { if ($handler::afterStatementAnalysis($event) === false) { return false; } } return null; } /** * @return list */ public function dispatchAddTaints(AddRemoveTaintsEvent $event): array { $added_taints = []; foreach ($this->add_taints_checks as $handler) { $added_taints = [...$added_taints, ...$handler::addTaints($event)]; } return $added_taints; } /** * @return list */ public function dispatchRemoveTaints(AddRemoveTaintsEvent $event): array { $removed_taints = []; foreach ($this->remove_taints_checks as $handler) { $removed_taints = [...$removed_taints, ...$handler::removeTaints($event)]; } return $removed_taints; } }