diff --git a/include/crow/mustache.h b/include/crow/mustache.h index e0e4889ec..88021df27 100644 --- a/include/crow/mustache.h +++ b/include/crow/mustache.h @@ -542,6 +542,13 @@ namespace crow // NOTE: Already documented in "crow/app.h" while (body_[endIdx - 1] == ' ') endIdx--; { + if (blockPositions.empty()) + { + throw invalid_template_exception( + std::string("unexpected closing tag: ") + + body_.substr(idx, endIdx - idx) + ); + } auto& matched = actions_[blockPositions.back()]; if (body_.compare(idx, endIdx - idx, body_, matched.start, matched.end - matched.start) != 0) diff --git a/tests/fuzz/template_fuzzer.cpp b/tests/fuzz/template_fuzzer.cpp index 62368c001..5686eac17 100644 --- a/tests/fuzz/template_fuzzer.cpp +++ b/tests/fuzz/template_fuzzer.cpp @@ -24,9 +24,9 @@ extern "C" int LLVMFuzzerTestOneInput(const std::uint8_t* data, const std::size_ auto ctx = build_context_object(fdp); page.render_string(ctx); } - catch (const crow::mustache::invalid_template_exception& e) + catch (const std::exception& e) { - return -1; + // No special handling for invalid inputs or rendering errors } return 0; diff --git a/tests/template/crow_extra_mustache_tests.json b/tests/template/crow_extra_mustache_tests.json index f81a18913..cb475f97f 100644 --- a/tests/template/crow_extra_mustache_tests.json +++ b/tests/template/crow_extra_mustache_tests.json @@ -9,6 +9,15 @@ }, "template": "\"{{#boolean}}{{^boolean}}\"", "expected": "COMPILE EXCEPTION: crow::mustache error: open tag has no matching end tag {{# {{/ pair: boolean" + }, + { + "name": "Unexpected end-tags", + "desc": "Unexpected end-tags should fail to render ... and not enter infinite loops or other undefined behaviour", + "data": { + "boolean": true + }, + "template": "\"{{/unexpected}}\"", + "expected": "COMPILE EXCEPTION: crow::mustache error: unexpected closing tag: unexpected" } ], "__ATTN__": "This file was hand-written"