Changeset 0aab93ba05631253155d0cdd5059158cae7f269b
- Timestamp:
- 09/23/09 20:36:22 (3 years ago)
- Author:
- Antti-Juhani Kaijanaho <antti-juhani@…>
- Children:
- 97ce4926752779cac0f6b8494b0cfdf096ee15f4
- Parents:
- 130a42d34f091a92300eb9988d79070c9cd22deb
- git-committer:
- Antti-Juhani Kaijanaho <antti-juhani@…> (09/23/09 20:36:22)
- Message:
-
[tlate::def] Set a limit to how many times a function can be called
The limit is of course arbitrary. The aim here is to protect against
overflowing the call stack with unbounded recursion in the template.
The downside of this fix is that it limits non-recursive calls as well.
A better fix would involve converting the evaluator into a bytecode
interpreter with an explicit call stack (this would allow monitoring
the actual stack usage instead of an indirect measure of calls).
Completes the fix of #12.
Signed-off-by: Antti-Juhani Kaijanaho <antti-juhani@…>
- Location:
- tlate
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
r26b574e
|
r0aab93b
|
|
| 33 | 33 | class closure : public value |
| 34 | 34 | { |
| | 35 | std::string name; |
| 35 | 36 | std::vector<std::string> parms; |
| 36 | 37 | seq::ptr body; |
| 37 | 38 | structured_value::ptr senv; |
| | 39 | mutable size_t &eval_count; |
| 38 | 40 | std::string fname; |
| 39 | 41 | int line; |
| … |
… |
|
| 42 | 44 | typedef boost::shared_ptr<const closure> const_ptr; |
| 43 | 45 | |
| 44 | | closure(std::vector<std::string> parms, |
| | 46 | closure(std::string name, |
| | 47 | std::vector<std::string> parms, |
| 45 | 48 | seq::ptr body, |
| 46 | 49 | structured_value::ptr senv, |
| | 50 | size_t &eval_count, |
| 47 | 51 | std::string fname, |
| 48 | 52 | int line) |
| 49 | | : parms(parms) |
| | 53 | : name(name) |
| | 54 | , parms(parms) |
| 50 | 55 | , body(body) |
| 51 | 56 | , senv(senv) |
| | 57 | , eval_count(eval_count) |
| 52 | 58 | , fname(fname) |
| 53 | 59 | , line(line) |
| … |
… |
|
| 63 | 69 | std::string fname, int line) const |
| 64 | 70 | { |
| | 71 | if (eval_count++ > 5000) |
| | 72 | { |
| | 73 | logger::logline ll; |
| | 74 | ll << this->fname << ":" << this->line |
| | 75 | << ": too many calls to " << name; |
| | 76 | return empty_value::instance(); |
| | 77 | } |
| 65 | 78 | overriding_structured_value::ptr env |
| 66 | 79 | (new overriding_structured_value(senv)); |
| … |
… |
|
| 89 | 102 | def::def(scanner &sc) |
| 90 | 103 | : tlate(sc.peekFileName(), sc.peekLineNo()) |
| | 104 | , eval_count(0) |
| 91 | 105 | { |
| 92 | 106 | /* |
| … |
… |
|
| 132 | 146 | it != bodyfvs.end(); it++) |
| 133 | 147 | senv->insert(*it, env->get(*it)); |
| 134 | | value::ptr cl(new closure(parms, body, senv, fname, line)); |
| | 148 | value::ptr cl(new closure(name, parms, body, senv, eval_count, |
| | 149 | fname, line)); |
| 135 | 150 | senv->insert(name, cl); |
| 136 | 151 | env->override(name, cl); |
-
|
r26b574e
|
r0aab93b
|
|
| 38 | 38 | seq::ptr body; |
| 39 | 39 | std::set<std::string> bodyfvs; |
| | 40 | size_t eval_count; |
| 40 | 41 | public: |
| 41 | 42 | typedef boost::shared_ptr<def> ptr; |