88use SplTempFileObject ;
99use Stringable ;
1010
11+ use function array_key_exists ;
1112use function array_pop ;
1213use function explode ;
14+ use function in_array ;
1315use function preg_match ;
1416use function substr ;
1517
@@ -19,6 +21,8 @@ final class Rules implements PublicSuffixList
1921 private const PRIVATE_DOMAINS = 'PRIVATE_DOMAINS ' ;
2022 private const UNKNOWN_DOMAINS = 'UNKNOWN_DOMAINS ' ;
2123
24+ private const DOMAIN_RULE_MARKER = '? ' ;
25+
2226 private const REGEX_PSL_SECTION = ',^// ===(?<point>BEGIN|END) (?<type>ICANN|PRIVATE) DOMAINS===, ' ;
2327 private const PSL_SECTION = [
2428 'ICANN ' => [
@@ -134,7 +138,13 @@ private static function addRule(array $list, array $ruleParts): array
134138 $ isDomain = false ;
135139 }
136140
137- $ list [$ rule ] = $ list [$ rule ] ?? ($ isDomain ? [] : ['! ' => '' ]);
141+ if (isset ($ list [$ rule ]) && [] === $ list [$ rule ]) {
142+ $ list [$ rule ] = [self ::DOMAIN_RULE_MARKER => '' ];
143+ }
144+ if (!isset ($ list [$ rule ])) {
145+ $ list [$ rule ] = $ isDomain ? [] : ['! ' => '' ];
146+ }
147+
138148 if ($ isDomain && [] !== $ ruleParts ) {
139149 /** @var array<array-key, array> $tmpList */
140150 $ tmpList = $ list [$ rule ];
@@ -264,6 +274,9 @@ private function getPublicSuffixLengthFromSection(DomainName $domain, string $se
264274 //no match found
265275 if (!array_key_exists ($ label , $ rules )) {
266276 // Suffix MUST be fully matched else no suffix is found for private domain
277+ if (self ::PRIVATE_DOMAINS === $ section && array_key_exists (self ::DOMAIN_RULE_MARKER , $ rules )) {
278+ return $ labelCount ;
279+ }
267280 if (self ::PRIVATE_DOMAINS === $ section && self ::hasRemainingRules ($ rules )) {
268281 $ labelCount = 0 ;
269282 }
0 commit comments