-
-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent infinite loop in function lookup #34
Conversation
Excellent stuff. I wonder, could we have a custom error here that says that the max has been exceeded and that they could tweak the variable in whichever file if they need a higher limit? |
I have a feeling that I opened an issue somewhere because there are two versions of the templating module; One in shared resources and one elsewhere. But I now can't find the other issue. If that is the case do we need to duppicate these changes? Or preferably put tempting in its own module? |
As suggested by @adamretter
@adamretter Great idea to improve the error message. I've committed this. Thanks! Yes, the "old" dashboard contained a copy of the templating module - see https://github.com/eXist-db/dashboard/blob/master/modules/templates.xql. But luckily the "new" dashboard dropped it - see https://github.com/eXist-db/existdb-dashboard/tree/master/modules. |
@adamretter Incidentally, this made me wish for a 1-arity version of These, combined with some of the functions from the inspect module and the util functions for retrieving available modules and functions might make good candidates for inclusion in an EXPath spec (: if not XQuery 3.2 :). This could fit in nicely with @lcahlander’s XQDoc project. |
So I think creating an EXPath reflection module is probably the best chance of success for such things. Would be happy to collaborate on it with you |
@adamretter Thanks for the review & merge and these comments. I wasn't familiar with the term reflection, but if that's the umbrella term that this would fall under, it sounds great. Perhaps once HTTP v2 is done and the community issues are a little more settled. |
The problem
#29 (released in https://github.com/eXist-db/shared-resources/releases/tag/v0.5.0) added the following feature:
... but this enhancement introduced a bug, reported in #33: If a template references a non-existent function, the request for this template hangs indefinitely, and the query has to be manually killed.
Diagnosis
The problem was caused by an infinite loop in
templates:resolve()
, which looks up a function named in a template call. It checks to see if a function of the given name and arity 2 exists (this would correspond to a basic templating function that contains 2 parameters,$node
and$model
); if no function at this arity is found, the check is performed again, incrementing the arity by 1, and again recursively—with no bound.This recursive check for arity is needed, since the function called may take fewer or greater than the number of parameters supplied in the template; the templating module allows parameters to come from at least 3 other locations (URL parameters, request attributes, and session attributes), with an extension mechanism for developers to supply their own ordered set of parameter sources. So the templating module has no way to know in advance the arity to apply. Instead, it needs to find a function whose arity matches. It proceeds from least to greatest arity. But there's currently no upper bound, meaning that missing functions lead to an infinite loop.
Solutions
One solution would be to enforce an upper bound for arity in the
$lookup
(or$resolve
) function they supply totemplates:apply()
in their apps'modules/view.xql
query:However, that would require changes in apps that previously worked before #29, and it would impose a burden on all apps that wanted to insulate themselves from this problem.
The approach taken in this PR is to move the maximum arity value into the templating function, hard-coding the previous limit of 20 for templating function arity. This limit was adequate before #29 and could always be adjusted upward if needed in a future PR.
Result
Now, if a non-existent function is referenced, the templating module immediately returns an error:
Closes #33.