Skip to content

Commit 85e39d4

Browse files
committed
Restrict access for DOM classes
1 parent 04020f9 commit 85e39d4

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

src/Type/ObjectType.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,16 @@ class ObjectType implements TypeWithClassName, SubtractableType
6161
use UndecidedComparisonTypeTrait;
6262
use NonGeneralizableTypeTrait;
6363

64-
private const EXTRA_OFFSET_CLASSES = ['SimpleXMLElement', 'DOMNodeList', 'Threaded'];
64+
private const EXTRA_OFFSET_CLASSES = [
65+
'DOMNamedNodeMap',
66+
'Dom\NamedNodeMap',
67+
'DOMNodeList',
68+
'Dom\NodeList',
69+
'Dom\HTMLCollection',
70+
'Dom\DtdNamedNodeMap',
71+
'SimpleXMLElement',
72+
'Threaded',
73+
];
6574

6675
private ?Type $subtractedType;
6776

@@ -1067,19 +1076,26 @@ public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
10671076
: new BooleanType();
10681077
}
10691078

1070-
private function isExtraOffsetAccessibleClass(): TrinaryLogic
1079+
private function isExtraOffsetAccessibleClass(AccessOffsetMode $mode): TrinaryLogic
10711080
{
10721081
$classReflection = $this->getClassReflection();
10731082
if ($classReflection === null) {
10741083
return TrinaryLogic::createMaybe();
10751084
}
10761085

1086+
// TODO Narrow down NodeList/Map types
10771087
foreach (self::EXTRA_OFFSET_CLASSES as $extraOffsetClass) {
1078-
if ($classReflection->getName() === $extraOffsetClass) {
1079-
return TrinaryLogic::createYes();
1080-
}
1081-
if ($classReflection->isSubclassOf($extraOffsetClass)) {
1082-
return TrinaryLogic::createYes();
1088+
if (
1089+
$classReflection->getName() === $extraOffsetClass
1090+
|| $classReflection->isSubclassOf($extraOffsetClass)
1091+
) {
1092+
return match ($extraOffsetClass) {
1093+
'DOMNamedNodeMap', 'Dom\NamedNodeMap', 'DOMNodeList', 'Dom\NodeList', 'Dom\HTMLCollection', 'Dom\DtdNamedNodeMap' => match ($mode) {
1094+
AccessOffsetMode::Read, AccessOffsetMode::Exist => TrinaryLogic::createYes(),
1095+
default => TrinaryLogic::createNo(),
1096+
},
1097+
default => TrinaryLogic::createYes(),
1098+
};
10831099
}
10841100
}
10851101

@@ -1097,14 +1113,16 @@ private function isExtraOffsetAccessibleClass(): TrinaryLogic
10971113
public function isOffsetAccessible(): TrinaryLogic
10981114
{
10991115
return $this->isInstanceOf(ArrayAccess::class)->or(
1100-
$this->isExtraOffsetAccessibleClass(),
1116+
// TODO Back propagate this?
1117+
$this->isExtraOffsetAccessibleClass(AccessOffsetMode::Read),
11011118
);
11021119
}
11031120

11041121
public function isOffsetAccessLegal(AccessOffsetMode $mode): TrinaryLogic
11051122
{
1106-
// TODO Narrow down NodeList/Map types
1107-
return $this->isOffsetAccessible();
1123+
return $this->isInstanceOf(ArrayAccess::class)->or(
1124+
$this->isExtraOffsetAccessibleClass($mode),
1125+
);
11081126
}
11091127

11101128
public function hasOffsetValueType(Type $offsetType): TrinaryLogic

0 commit comments

Comments
 (0)