Assertion abort on `{{a[()}}` (unchecked expected after a failed subscript)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 88/100
Research direction
Start in src/expression_parser.cpp:333-336 and reproduce the abort with {{a[()]}}, also checking the other examples in the issue. Trace the ParseSubscript result before the ParseCall path; done means Template::Load returns a parse error for the unterminated subscript instead of aborting or reaching undefined behaviour.
Written by the indexing model from the issue text.
Description
The parser dereferences the result of ParseSubscript without checking whether it holds an error. When the subscript fails and the next token is (, the error value reaches ParseCall, and expected::operator* asserts.
Affected: master 79af49f. The same code is present in releases 1.1.0, 1.2.1 and 1.3.2.
Reproduction
Template:
{{a[()}}
Loading it aborts:
Assertion `has_value()' failed.
#0 ... nonstd::expected_lite::expected<...>::operator*() at third_party/nonstd/include/nonstd/expected.hpp:2254
#1 jinja2::ExpressionParser::ParseValueExpression(jinja2::LexScanner&) at src/expression_parser.cpp:336
{{endmacro[()}} and {{a[(]()}} abort the same way.
Expected: Template::Load returns a parse error for the unterminated subscript, as Jinja2 does.
Actual: the process aborts before a parse error is returned. With -DNDEBUG the assert compiles out and the same line reads the error storage, which is undefined behaviour.
Issue #252 reports the same class of unchecked expected access from a different parse path.
Root cause
src/expression_parser.cpp:333-336:
if (tok == '[' || tok == '.')
valueRef = ParseSubscript(lexer, *valueRef);
if (lexer.EatIfEqual('('))
valueRef = ParseCall(lexer, *valueRef);
ParseSubscript returns an expected that can hold a ParseError. The ParseCall line dereferences that result without checking it first.
- Dominant language
- C++
- Stars
- 600
- Forks
- 114
- PR merge metrics
- No merged PRs in 30d
Getting set up
We have not checked this project's setup files yet. Start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from jinja2cpp/Jinja2Cpp
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 4/5 3-5 days Newbie friendliness 65/100
-
Difficulty 3/5 1-2 days Newbie friendliness 74/100
-
Difficulty 3/5 1-2 days Newbie friendliness 70/100
-
Difficulty 3/5 1-2 days Newbie friendliness 35/100
All issues in jinja2cpp/Jinja2Cpp
Similar issues
-
Unconfirmed bug
Difficulty 1/5 Under an hour Newbie friendliness 88/100
luanti-org/luanti#17605 · 1 comment ·
Maintainers usually reply within 2 days
-
area: config area: firmware priority: P2 - medium size: S type: bug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Mizithra/ActiveTerrain#16 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
grumpycoders/pcsx-redux#2171 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
bytedance/trae-agent#524 · 1 comment ·
Maintainers usually reply within 1 day