3v4l.org

run code in 300+ PHP versions simultaneously
<?php const STAR_PROTECTOR = '__zqh6vxfbk3cg__'; function load($html) { $html = str_replace('*', STAR_PROTECTOR, $html); $document = <<<EOD <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head> <body>!html</body> </html> EOD; // PHP's \DOMDocument serialization adds extra whitespace when the markup // of the wrapping document contains newlines, so ensure we remove all // newlines before injecting the actual HTML body to be processed. $document = strtr($document, ["\n" => '', '!html' => $html]); $dom = new \DOMDocument(); // Ignore warnings during HTML soup loading. @$dom->loadHTML($document); return $dom; } function simulate_filter_html_parsing(string $input) { print "-----\n$input\n-----\n"; $parsed_nodes = load($input)->getElementsByTagName('body')->item(0)->childNodes; foreach ($parsed_nodes as $node) { // ⚠️ See @larowlan's https://www.drupal.org/project/drupal/issues/3280602#comment-14517052 comment if ($node->nodeType !== XML_ELEMENT_NODE) { // Skip the empty text nodes inside tags. continue; } print 'tag: '; var_dump($node->tagName); foreach ($node->attributes as $name => $attribute) { // Put back any trailing * on wildcard attribute name. $name = str_replace(STAR_PROTECTOR, '*', $name); // Put back any trailing * on wildcard attribute value and parse out // the allowed attribute values. $allowed_attribute_values = preg_split('/\s+/', str_replace(STAR_PROTECTOR, '*', $attribute->value), -1, PREG_SPLIT_NO_EMPTY); print 'attr: '; var_dump($name); // if ($attr-) if (!empty($allowed_attribute_values)) { print 'attr values: '; var_dump($allowed_attribute_values); } } } print "\n\n"; } // ⚠️ Uncomment this if you want to convince yourself this really is running for all PHP versions // print phpversion() . "\n"; simulate_filter_html_parsing('<foo data-*>'); simulate_filter_html_parsing('<foo data-*="foo bar">'); simulate_filter_html_parsing('<__preprocessed-global-attribute__ data-*="foo bar">'); // ⚠️ This is the specific example @larowlan cited at https://www.drupal.org/project/drupal/issues/3280602#comment-14517052 simulate_filter_html_parsing('<__preprocessed-wildcard-text-container__ class="text-align-left text-align-center text-align-right text-align-justify" />'); // ⚠️ 3vl.org unfortunately has disabled phpinfo for security reasons… so we cannot check the libxml version //var_dump(phpinfo(INFO_MODULES));
Output for 7.4.0 - 7.4.33, 8.0.1 - 8.0.30, 8.1.0 - 8.1.33, 8.2.0 - 8.2.29, 8.3.0 - 8.3.28, 8.4.1 - 8.4.14, 8.4.16, 8.5.0 - 8.5.1
----- <foo data-*> ----- tag: string(3) "foo" attr: string(6) "data-*" ----- <foo data-*="foo bar"> ----- tag: string(3) "foo" attr: string(6) "data-*" attr values: array(2) { [0]=> string(3) "foo" [1]=> string(3) "bar" } ----- <__preprocessed-global-attribute__ data-*="foo bar"> ----- tag: string(33) "__preprocessed-global-attribute__" attr: string(6) "data-*" attr values: array(2) { [0]=> string(3) "foo" [1]=> string(3) "bar" } ----- <__preprocessed-wildcard-text-container__ class="text-align-left text-align-center text-align-right text-align-justify" /> ----- tag: string(40) "__preprocessed-wildcard-text-container__" attr: string(5) "class" attr values: array(4) { [0]=> string(15) "text-align-left" [1]=> string(17) "text-align-center" [2]=> string(16) "text-align-right" [3]=> string(18) "text-align-justify" }
Output for 8.4.15
/bin/php-8.4.15: /usr/lib/libm.so.6: version `GLIBC_2.38' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libm.so.6: version `GLIBC_2.35' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libc.so.6: version `GLIBC_2.34' not found (required by /bin/php-8.4.15) /bin/php-8.4.15: /usr/lib/libc.so.6: version `GLIBC_2.38' not found (required by /bin/php-8.4.15)
Process exited with code 1.

preferences:
168.95 ms | 408 KiB | 5 Q