Loading _test/general.test.php +8 −8 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest $failureMsg = 'Assertion failed at expression "' . $expr . '".'; $ast = null; $rebuiltExpr = null; $this->assertNotNull($ast = parse($expr)); $this->assertNotNull($ast = auth_expr_parse($expr)); $this->assertNotNull($rebuiltExpr = $ast->getRepresentation()); $this->assertEquals($rebuiltExpr, preg_replace('/\s/', '', $expr)); } Loading @@ -133,7 +133,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::UNKNOWN_TOKEN_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -146,7 +146,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::UNMATCHED_WRAPPER_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -160,7 +160,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::NOT_ENOUGH_ARGS_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -175,7 +175,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest try { $ast = null; // The expression must parse, but not validate $this->assertNotNull($ast = parse($expr)); $this->assertNotNull($ast = auth_expr_parse($expr)); $ast->ensureWellFormed(); } catch (Exception $e) { $exc = $e; Loading @@ -186,16 +186,16 @@ class general_plugin_ifauthex_test extends DokuWikiTest public function test_empty_parentehses() { // This must not throw. It's malformed, but it's parsed correctly. $this->assertNotNull(parse('()')); $this->assertNotNull(auth_expr_parse('()')); } public function test_depth_limit() { global $EXPR_DEPTH_LIMIT; $depthLimit = \AST\parse_config()->EXPR_DEPTH_LIMIT; $this->expectException(RuntimeException::class); parse(str_repeat('(', $EXPR_DEPTH_LIMIT) . 'a && b' . str_repeat(')', $EXPR_DEPTH_LIMIT)); auth_expr_parse(str_repeat('(', $depthLimit) . 'a && b' . str_repeat(')', $depthLimit)); } /** Loading lib/grammar.php +25 −8 Original line number Diff line number Diff line Loading @@ -118,15 +118,32 @@ class OpOr extends ElementDefinition { } } function auth_expr_all_elements() { static $ALL_ELEMENTS = null; if ($ALL_ELEMENTS === null) { $ALL_ELEMENTS = array(new Literal(), new SubExpr(), new OpInGroup(), new OpNot(), new OpAnd(), new OpOr()); } return $ALL_ELEMENTS; } function auth_expr_ignore_tokens() { static $IGNORE_TOKENS = null; if ($IGNORE_TOKENS === null) { $IGNORE_TOKENS = array(new TokenDefinition(' ', 'SPC', '/\s+/')); $ALL_TOKENS = array_merge($IGNORE_TOKENS, ElementDefinition::extractUsedTokens($ALL_ELEMENTS)); } return $IGNORE_TOKENS; } function auth_expr_all_tokens() { static $ALL_TOKENS = null; if ($ALL_TOKENS === null) { $ALL_TOKENS = array_merge(auth_expr_ignore_tokens(), ElementDefinition::extractUsedTokens(auth_expr_all_elements())); } return $ALL_TOKENS; } function parse($expr) { global $ALL_ELEMENTS; global $IGNORE_TOKENS; global $ALL_TOKENS; return \AST\parse(\AST\tokenize($expr, $ALL_TOKENS, $IGNORE_TOKENS), $ALL_ELEMENTS); function auth_expr_parse($expr) { return \AST\parse(\AST\tokenize($expr, auth_expr_all_tokens(), auth_expr_ignore_tokens()), auth_expr_all_elements()); } ?> No newline at end of file lib/parser.php +25 −15 Original line number Diff line number Diff line Loading @@ -8,7 +8,17 @@ use \RuntimeException; require_once "tokenizer.php"; require_once "exceptions.php"; $EXPR_DEPTH_LIMIT = 50; class ParseConfig { public $EXPR_DEPTH_LIMIT = 50; } function parse_config() { static $config = null; if ($config == null) { $config = new ParseConfig(); } return $config; } abstract class Fixing { const None = 0; Loading Loading @@ -43,8 +53,8 @@ class ElementInstance { } public function getRepresentation() { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -68,8 +78,8 @@ class ElementInstance { } public function isExpanded($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -88,8 +98,8 @@ class ElementInstance { } public function expand($elmDef, $recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -110,8 +120,8 @@ class ElementInstance { } public function findUnexpandedToken($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -135,8 +145,8 @@ class ElementInstance { } public function printTree($indentStr='', $isLastChild=false) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading Loading @@ -171,8 +181,8 @@ class ElementInstance { } public function ensureWellFormed($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -196,8 +206,8 @@ class ElementInstance { } public function evaluate() { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading Loading
_test/general.test.php +8 −8 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest $failureMsg = 'Assertion failed at expression "' . $expr . '".'; $ast = null; $rebuiltExpr = null; $this->assertNotNull($ast = parse($expr)); $this->assertNotNull($ast = auth_expr_parse($expr)); $this->assertNotNull($rebuiltExpr = $ast->getRepresentation()); $this->assertEquals($rebuiltExpr, preg_replace('/\s/', '', $expr)); } Loading @@ -133,7 +133,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::UNKNOWN_TOKEN_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -146,7 +146,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::UNMATCHED_WRAPPER_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -160,7 +160,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest foreach (self::NOT_ENOUGH_ARGS_EXPRESSIONS as $expr) { $exc = null; try { parse($expr); auth_expr_parse($expr); } catch (Exception $e) { $exc = $e; } Loading @@ -175,7 +175,7 @@ class general_plugin_ifauthex_test extends DokuWikiTest try { $ast = null; // The expression must parse, but not validate $this->assertNotNull($ast = parse($expr)); $this->assertNotNull($ast = auth_expr_parse($expr)); $ast->ensureWellFormed(); } catch (Exception $e) { $exc = $e; Loading @@ -186,16 +186,16 @@ class general_plugin_ifauthex_test extends DokuWikiTest public function test_empty_parentehses() { // This must not throw. It's malformed, but it's parsed correctly. $this->assertNotNull(parse('()')); $this->assertNotNull(auth_expr_parse('()')); } public function test_depth_limit() { global $EXPR_DEPTH_LIMIT; $depthLimit = \AST\parse_config()->EXPR_DEPTH_LIMIT; $this->expectException(RuntimeException::class); parse(str_repeat('(', $EXPR_DEPTH_LIMIT) . 'a && b' . str_repeat(')', $EXPR_DEPTH_LIMIT)); auth_expr_parse(str_repeat('(', $depthLimit) . 'a && b' . str_repeat(')', $depthLimit)); } /** Loading
lib/grammar.php +25 −8 Original line number Diff line number Diff line Loading @@ -118,15 +118,32 @@ class OpOr extends ElementDefinition { } } function auth_expr_all_elements() { static $ALL_ELEMENTS = null; if ($ALL_ELEMENTS === null) { $ALL_ELEMENTS = array(new Literal(), new SubExpr(), new OpInGroup(), new OpNot(), new OpAnd(), new OpOr()); } return $ALL_ELEMENTS; } function auth_expr_ignore_tokens() { static $IGNORE_TOKENS = null; if ($IGNORE_TOKENS === null) { $IGNORE_TOKENS = array(new TokenDefinition(' ', 'SPC', '/\s+/')); $ALL_TOKENS = array_merge($IGNORE_TOKENS, ElementDefinition::extractUsedTokens($ALL_ELEMENTS)); } return $IGNORE_TOKENS; } function auth_expr_all_tokens() { static $ALL_TOKENS = null; if ($ALL_TOKENS === null) { $ALL_TOKENS = array_merge(auth_expr_ignore_tokens(), ElementDefinition::extractUsedTokens(auth_expr_all_elements())); } return $ALL_TOKENS; } function parse($expr) { global $ALL_ELEMENTS; global $IGNORE_TOKENS; global $ALL_TOKENS; return \AST\parse(\AST\tokenize($expr, $ALL_TOKENS, $IGNORE_TOKENS), $ALL_ELEMENTS); function auth_expr_parse($expr) { return \AST\parse(\AST\tokenize($expr, auth_expr_all_tokens(), auth_expr_ignore_tokens()), auth_expr_all_elements()); } ?> No newline at end of file
lib/parser.php +25 −15 Original line number Diff line number Diff line Loading @@ -8,7 +8,17 @@ use \RuntimeException; require_once "tokenizer.php"; require_once "exceptions.php"; $EXPR_DEPTH_LIMIT = 50; class ParseConfig { public $EXPR_DEPTH_LIMIT = 50; } function parse_config() { static $config = null; if ($config == null) { $config = new ParseConfig(); } return $config; } abstract class Fixing { const None = 0; Loading Loading @@ -43,8 +53,8 @@ class ElementInstance { } public function getRepresentation() { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -68,8 +78,8 @@ class ElementInstance { } public function isExpanded($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -88,8 +98,8 @@ class ElementInstance { } public function expand($elmDef, $recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -110,8 +120,8 @@ class ElementInstance { } public function findUnexpandedToken($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -135,8 +145,8 @@ class ElementInstance { } public function printTree($indentStr='', $isLastChild=false) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading Loading @@ -171,8 +181,8 @@ class ElementInstance { } public function ensureWellFormed($recursive=true) { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading @@ -196,8 +206,8 @@ class ElementInstance { } public function evaluate() { static $stack_depth = 0; global $EXPR_DEPTH_LIMIT; if (++$stack_depth > $EXPR_DEPTH_LIMIT) { static $stack_depth = 0; if (++$stack_depth > parse_config()->EXPR_DEPTH_LIMIT) { throw new RuntimeException('Depth limit exceeded.'); } try { Loading