From beeda27483b7b68a7dad631c018006ede871497b Mon Sep 17 00:00:00 2001
From: Jan-Hendrik Willms <tleilax+studip@gmail.com>
Date: Fri, 3 Mar 2023 14:25:48 +0000
Subject: [PATCH] ensure only subclasses of AdmissionRule are instantiated,
 fixes #2236

Closes #2236

Merge request studip/studip!1474
---
 app/controllers/admission/rule.php | 31 ++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/app/controllers/admission/rule.php b/app/controllers/admission/rule.php
index 061cc4ee0f5..2a41db49c6c 100644
--- a/app/controllers/admission/rule.php
+++ b/app/controllers/admission/rule.php
@@ -92,7 +92,8 @@ class Admission_RuleController extends AuthenticatedController
     public function save_action($ruleType, $ruleId = '')
     {
         CSRFProtection::verifyUnsafeRequest();
-        $this->rule = new $ruleType($ruleId);
+
+        $this->rule = $this->loadRule($ruleType, $ruleId);
         $requestData = Request::getInstance();
         // Check for start and end date and parse the String values to timestamps.
         if (!empty($requestData['start_date'])) {
@@ -119,7 +120,33 @@ class Admission_RuleController extends AuthenticatedController
      */
     public function validate_action($ruleType, $ruleId = '')
     {
-        $rule = new $ruleType($ruleId);
+        $rule = $this->loadRule($ruleType, $ruleId);
         $this->errors = $rule->validate(Request::getInstance());
     }
+
+    /**
+     * Loads a rule by string and ensures that it is a subclass of the abstract
+     * admission rule.
+     *
+     * @param string $rule_type
+     * @param string $rule_id
+     * @return AdmissionRule
+     */
+    private function loadRule(string $rule_type, string $rule_id = ''): AdmissionRule
+    {
+        static $initialized = false;
+
+        if (!$initialized) {
+            // This is neccessary so that all admission rules are correctly
+            // loaded and known to the system
+            AdmissionRule::getAvailableAdmissionRules();
+            $initialized = true;
+        }
+
+        if (!is_a($rule_type, AdmissionRule::class, true)) {
+            throw new InvalidArgumentException('Rule type must be a subclass of ' . AdmissionRule::class);
+        }
+
+        return new $rule_type($rule_id);
+    }
 }
-- 
GitLab