diff --git a/components/ILIAS/RTE/classes/class.ilRTE.php b/components/ILIAS/RTE/classes/class.ilRTE.php
index c99c98303418..dd03d79f79b5 100755
--- a/components/ILIAS/RTE/classes/class.ilRTE.php
+++ b/components/ILIAS/RTE/classes/class.ilRTE.php
@@ -28,6 +28,13 @@
*/
class ilRTE
{
+ /**
+ * Media-object images are stored as src="…" data-id="123".
+ * The value must not cross the closing quote. A greedy ".*" backtracks
+ * over large data-URI payloads and hits the PCRE backtrack limit.
+ */
+ private const MEDIA_OBJECT_SRC_PATTERN = '/src="[^"]*" data-id="([0-9]+)"/';
+
protected ilGlobalTemplateInterface $tpl;
protected ilCtrlInterface $ctrl;
protected ilObjUser $user;
@@ -141,7 +148,7 @@ public static function _getRTEClassname(): string
public static function _cleanupMediaObjectUsage(string $a_text, string $a_usage_type, int $a_usage_id): void
{
$mobs = ilObjMediaObject::_getMobsOfObject($a_usage_type, $a_usage_id);
- while (preg_match('/src=".*" data-id="([0-9]+)"/', $a_text, $found)) {
+ while (preg_match(self::MEDIA_OBJECT_SRC_PATTERN, $a_text, $found)) {
$a_text = str_replace($found[0], '', $a_text);
$found_mob_id = (int) $found[1];
@@ -185,11 +192,16 @@ public static function _replaceMediaObjectImageSrc(
}
if ($a_direction === 0) {
- $a_text = preg_replace(
- '/src=".*" data-id="([0-9]+)"/',
- 'src="il_' . $nic . '_mob_\\1"',
+ $replaced = preg_replace_callback(
+ self::MEDIA_OBJECT_SRC_PATTERN,
+ static fn (array $match): string => 'src="il_' . $nic . '_mob_' . $match[1] . '"',
$a_text
);
+ // A PCRE failure returns null. Keep the original text instead of
+ // violating the string return type.
+ if (is_string($replaced)) {
+ $a_text = $replaced;
+ }
} else {
$resulttext = $a_text;
if (preg_match_all('/src="(il_[0-9]+_mob_([0-9]+))"/', $a_text, $matches)) {
@@ -221,7 +233,7 @@ public static function _getMediaObjects(string $a_text, int $a_direction = 0): a
$mediaObjects = [];
if ($a_direction === 0) {
- $is_matching = preg_match_all('/src=".*" data-id="([0-9]+)"/', $a_text, $matches);
+ $is_matching = preg_match_all(self::MEDIA_OBJECT_SRC_PATTERN, $a_text, $matches);
} else {
$is_matching = preg_match_all('/src="il_[0-9]+_mob_([0-9]+)"/', $a_text, $matches);
}
diff --git a/components/ILIAS/RTE/tests/ilRTEMediaObjectImageSrcTest.php b/components/ILIAS/RTE/tests/ilRTEMediaObjectImageSrcTest.php
new file mode 100644
index 000000000000..bd0c4d09eae2
--- /dev/null
+++ b/components/ILIAS/RTE/tests/ilRTEMediaObjectImageSrcTest.php
@@ -0,0 +1,64 @@
+
';
+
+ $result = ilRTE::_replaceMediaObjectImageSrc($html, 0, '7');
+
+ $this->assertSame(
+ '
';
+
+ $result = ilRTE::_replaceMediaObjectImageSrc($html, 0, '1$2');
+
+ $this->assertSame('