mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 00:32:42 +01:00
Prevent embedded remarkup content from cycling when it contains embedded self-references
Summary: Ref T13678. When remarkup content embeds other remarkup content, detect and degrade if the references have nesting depth greater than 1. This is a coarse cycle detector, since rendering shallow (but technically non-cycling) trees doesn't seem valuable. Test Plan: Created various objects with self-references, saw everything degrade properly (after one level of embedding) when embedded in itself and in other contexts. See attached screenshot. Maniphest Tasks: T13678 Differential Revision: https://secure.phabricator.com/D21810
This commit is contained in:
parent
a640a4a493
commit
01253d533b
2 changed files with 32 additions and 0 deletions
|
@ -46,6 +46,8 @@ final class PhabricatorMarkupEngine extends Phobject {
|
||||||
private $engineCaches = array();
|
private $engineCaches = array();
|
||||||
private $auxiliaryConfig = array();
|
private $auxiliaryConfig = array();
|
||||||
|
|
||||||
|
private static $engineStack = array();
|
||||||
|
|
||||||
|
|
||||||
/* -( Markup Pipeline )---------------------------------------------------- */
|
/* -( Markup Pipeline )---------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -103,6 +105,24 @@ final class PhabricatorMarkupEngine extends Phobject {
|
||||||
* @task markup
|
* @task markup
|
||||||
*/
|
*/
|
||||||
public function process() {
|
public function process() {
|
||||||
|
self::$engineStack[] = $this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $this->execute();
|
||||||
|
} finally {
|
||||||
|
array_pop(self::$engineStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isRenderingEmbeddedContent() {
|
||||||
|
// See T13678. This prevents cycles when rendering embedded content that
|
||||||
|
// itself has remarkup fields.
|
||||||
|
return (count(self::$engineStack) > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function execute() {
|
||||||
$keys = array();
|
$keys = array();
|
||||||
foreach ($this->objects as $key => $info) {
|
foreach ($this->objects as $key => $info) {
|
||||||
if (!isset($info['markup'])) {
|
if (!isset($info['markup'])) {
|
||||||
|
|
|
@ -126,6 +126,12 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
|
||||||
return $this->renderObjectTagForMail($name, $href, $handle);
|
return $this->renderObjectTagForMail($name, $href, $handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See T13678. If we're already rendering embedded content, render a
|
||||||
|
// default reference instead to avoid cycles.
|
||||||
|
if (PhabricatorMarkupEngine::isRenderingEmbeddedContent()) {
|
||||||
|
return $this->renderDefaultObjectEmbed($object, $handle);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->renderObjectEmbed($object, $handle, $options);
|
return $this->renderObjectEmbed($object, $handle, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +139,12 @@ abstract class PhabricatorObjectRemarkupRule extends PhutilRemarkupRule {
|
||||||
$object,
|
$object,
|
||||||
PhabricatorObjectHandle $handle,
|
PhabricatorObjectHandle $handle,
|
||||||
$options) {
|
$options) {
|
||||||
|
return $this->renderDefaultObjectEmbed($object, $handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected function renderDefaultObjectEmbed(
|
||||||
|
$object,
|
||||||
|
PhabricatorObjectHandle $handle) {
|
||||||
|
|
||||||
$name = $handle->getFullName();
|
$name = $handle->getFullName();
|
||||||
$href = $handle->getURI();
|
$href = $handle->getURI();
|
||||||
|
|
Loading…
Reference in a new issue