Skip to content
Snippets Groups Projects
Commit bb4337dd authored by Matti Harjula's avatar Matti Harjula
Browse files

Add special handling for calling of results of calls. Should stop the infinite...

Add special handling for calling of results of calls. Should stop the infinite recursion. Also now the filter tester can be asked to only output a particular filters results.
parent 1e0bfaf5
Branches
No related tags found
No related merge requests found
...@@ -35,7 +35,7 @@ require_once(__DIR__ . '/../stack/utils.class.php'); ...@@ -35,7 +35,7 @@ require_once(__DIR__ . '/../stack/utils.class.php');
// Now get cli options. // Now get cli options.
list($options, $unrecognized) = cli_get_params(array('help' => false, list($options, $unrecognized) = cli_get_params(array('help' => false,
'string' => '1+2x', 'ast' => false), array('h' => 'help')); 'string' => '1+2x', 'ast' => false, 'only' => false), array('h' => 'help'));
if ($unrecognized) { if ($unrecognized) {
$unrecognized = implode("\n ", $unrecognized); $unrecognized = implode("\n ", $unrecognized);
cli_error(get_string('cliunknowoption', 'admin', $unrecognized)); cli_error(get_string('cliunknowoption', 'admin', $unrecognized));
...@@ -45,6 +45,10 @@ if ($options['help']) { ...@@ -45,6 +45,10 @@ if ($options['help']) {
"Test the AST filters on a given string. "Test the AST filters on a given string.
--string=\"1+2x\" --string=\"1+2x\"
Limit to specific filter with:
--only=910
"; ";
echo $help; echo $help;
die; die;
...@@ -60,6 +64,10 @@ $astonly = false; ...@@ -60,6 +64,10 @@ $astonly = false;
if (isset($options['ast'])) { if (isset($options['ast'])) {
$astonly = $options['ast']; $astonly = $options['ast'];
} }
$only = false;
if (isset($options['only'])) {
$only = $options['only'];
}
cli_heading('= testing = ' . $teststring . ' ='); cli_heading('= testing = ' . $teststring . ' =');
...@@ -118,6 +126,15 @@ function check_filter($ast, $filter, $security, $filtername) { ...@@ -118,6 +126,15 @@ function check_filter($ast, $filter, $security, $filtername) {
cli_heading('= Every filter on its own on the raw AST, without units ='); cli_heading('= Every filter on its own on the raw AST, without units =');
$filters = stack_parsing_rule_factory::list_filters(); $filters = stack_parsing_rule_factory::list_filters();
if ($only !== false) {
$f = [];
foreach ($filters as $filter) {
if (strpos($filter, $only) !== false) {
$f[] = $filter;
}
}
$filters = $f;
}
sort($filters); sort($filters);
foreach ($filters as $filtername) { foreach ($filters as $filtername) {
$filter = stack_parsing_rule_factory::get_by_common_name($filtername); $filter = stack_parsing_rule_factory::get_by_common_name($filtername);
...@@ -146,6 +163,7 @@ foreach ($filters as $filtername) { ...@@ -146,6 +163,7 @@ foreach ($filters as $filtername) {
check_filter($freshast, $filter, new stack_cas_security(true), $filtername); check_filter($freshast, $filter, new stack_cas_security(true), $filtername);
} }
if ($only === false) {
cli_heading('= core + security(s) ='); cli_heading('= core + security(s) =');
$freshast = null; $freshast = null;
if ($parseable) { if ($parseable) {
...@@ -155,7 +173,7 @@ if ($parseable) { ...@@ -155,7 +173,7 @@ if ($parseable) {
'letToken' => stack_string('equiv_LET'))); 'letToken' => stack_string('equiv_LET')));
} }
$pipeline = stack_parsing_rule_factory::get_filter_pipeline(array('998_security'), $pipeline = stack_parsing_rule_factory::get_filter_pipeline(array('996_call_modification', '998_security'),
array('998_security' => array('security' => 's')), true); array('998_security' => array('security' => 's')), true);
check_filter($freshast, $pipeline, new stack_cas_security(false), 'core + security(s)'); check_filter($freshast, $pipeline, new stack_cas_security(false), 'core + security(s)');
...@@ -168,6 +186,7 @@ if ($parseable) { ...@@ -168,6 +186,7 @@ if ($parseable) {
'letToken' => stack_string('equiv_LET'))); 'letToken' => stack_string('equiv_LET')));
} }
$pipeline = stack_parsing_rule_factory::get_filter_pipeline(array('998_security', '999_strict'), $pipeline = stack_parsing_rule_factory::get_filter_pipeline(array('996_call_modification', '998_security', '999_strict'),
array('998_security' => array('security' => 't')), true); array('998_security' => array('security' => 't')), true);
check_filter($freshast, $pipeline, new stack_cas_security(false), 'core + security(t) + strict'); check_filter($freshast, $pipeline, new stack_cas_security(false), 'core + security(t) + strict');
}
...@@ -50,7 +50,6 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter { ...@@ -50,7 +50,6 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter {
} }
$p = $p->parentnode; $p = $p->parentnode;
} }
if ($node->name instanceof MP_Atom && ($node->name->value === self::IDCHECK || if ($node->name instanceof MP_Atom && ($node->name->value === self::IDCHECK ||
$node->name->value === self::EXPCHECK || $node->name->value === 'lambda')) { $node->name->value === self::EXPCHECK || $node->name->value === 'lambda')) {
// No checks for the checks themselves. They are protected using other means. // No checks for the checks themselves. They are protected using other means.
...@@ -58,6 +57,13 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter { ...@@ -58,6 +57,13 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter {
return true; return true;
} }
$namecheck = new MP_FunctionCall(new MP_Identifier(self::IDCHECK), [$node->name]); $namecheck = new MP_FunctionCall(new MP_Identifier(self::IDCHECK), [$node->name]);
if ($node->parentnode instanceof MP_FunctionCall && $node->parentnode->name === $node) {
// This case has been handled when that parent was handled.
return true;
}
// The order of these ifs is critical, we build up the checks // The order of these ifs is critical, we build up the checks
// so that no basic check gets lost due to more advanced ones // so that no basic check gets lost due to more advanced ones
// doing more conplex things. The advanced cases assume that // doing more conplex things. The advanced cases assume that
...@@ -86,6 +92,46 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter { ...@@ -86,6 +92,46 @@ class stack_ast_filter_996_call_modification implements stack_cas_astfilter {
return true; return true;
} }
// In the case of calling function/indexing results. f(x)(y) => (%_C(f),%_C(f(x)),f(x)(y))
if ($node->name instanceof MP_FunctionCall) {
$replacement = [$node];
$i = null;
if ($node instanceof MP_FunctionCall) {
$i = $node->name;
} else if ($node instanceof MP_Indexing) {
$i = $node->target;
}
while ($i !== null) {
array_unshift($replacement, new MP_FunctionCall(new MP_Identifier(self::IDCHECK), [$i]));
if ($i instanceof MP_FunctionCall) {
$i = $i->name;
} else if ($i instanceof MP_Indexing) {
$i = $i->target;
} else {
$i = null;
}
}
$replacement = new MP_Group($replacement);
// Has the full set already been done.
if ($node->parentnode instanceof MP_Group &&
count($node->parentnode->items) === count($replacement->items) &&
$node->parentnode->toString() === $replacement->toString()) {
return true;
}
}
// The previous one generates a pattern (...,%_C(f(x)),%_C(f(x)(y)),...)
// In this situation it is necessary to stop rewriting the call inside the check.
if ($node instanceof MP_FunctionCall && $node->parentnode instanceof MP_FunctionCall &&
$node->parentnode->name instanceof MP_Identifier &&
$node->parentnode->name->value === self::IDCHECK &&
$node->parentnode->parentnode instanceof MP_Group) {
$i = array_search($node->parentnode, $node->parentnode->parentnode->items, true);
if ($i >= 0 && $node->parentnode->parentnode->items[$i-1]->toString() ===
(new MP_FunctionCall(new MP_Identifier(self::IDCHECK), [$node->name]))->toString()) {
return true;
}
}
// In the case of a pattern f(x) => (%_C(f),f(x)). // In the case of a pattern f(x) => (%_C(f),f(x)).
$node->parentnode->replace($node, $replacement); $node->parentnode->replace($node, $replacement);
return false; return false;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment