From 365f9aa387d95a970217d8c234c51716bb1755d5 Mon Sep 17 00:00:00 2001 From: Benjamin Urquhart Date: Fri, 8 Aug 2025 00:22:39 -0400 Subject: [PATCH 1/2] Allow string interpolation to be toggled when using --cli --- src/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 8eeae2b..55d8c8e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,6 +76,7 @@ int main(int argc, char** argv) ("D,privname", "Name of output private translation file", cxxopts::value(), "(default: \"out\")") ("d,privdir", "Directory to output private translation files", cxxopts::value(), "(default: \"./translations\")") ("C,compress", "Whether or not to use compression") + ("I,nointerpolate", "Whether string interpolation should be disabled") ("files", "File(s) to compile", cxxopts::value>()->default_value("")); @@ -424,7 +425,8 @@ int main(int argc, char** argv) project.options.translationPrivateName = result["privname"].count() == 1 ? result["privname"].as() : "out"; project.options.translationPrivateOutDir = result["privdir"].count() == 1 ? result["privdir"].as() : "./translations"; project.options.compression = result["compress"].count() == 1 ? result["compress"].as() : false; - loaded = true; + project.options.interpolationEnabled = result["nointerpolate"].count() == 0; + loaded = true; } if (!loaded) @@ -756,4 +758,4 @@ int main(int argc, char** argv) std::cout << "Took " << duration.count() << " milliseconds." << rang::fg::reset << std::endl; return 0; -} \ No newline at end of file +} From 56b9bede1dbe7394a1bbc52f5f5d8a859660d047 Mon Sep 17 00:00:00 2001 From: Benjamin Urquhart Date: Fri, 8 Aug 2025 00:23:01 -0400 Subject: [PATCH 2/2] Fix oob read when parsing malformed interpolated string --- src/Parser.cpp | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Parser.cpp b/src/Parser.cpp index 530b508..2b63912 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -69,7 +69,7 @@ namespace diannex { pos++; count++; - if (input.at(pos) == '\n') + if (pos < len && input.at(pos) == '\n') { tempLine++; tempCol = 0; @@ -77,24 +77,36 @@ namespace diannex else tempCol++; } - std::string exprStr = input.substr(startPos, count); - - // Parse expression and add to nodes - std::vector tokens; - Lexer::LexString(exprStr, parser->context, tokens, line, col); - ParseResult parsed = Parser::ParseTokensExpression(parser->context, &tokens, line, col); - if (parsed.errors.size() != 0) - parser->errors.insert(parser->errors.end(), parsed.errors.begin(), parsed.errors.end()); + char lastChar; + + if (pos >= len) + lastChar = input.at(len - 1); else + lastChar = input.at(pos); + + if (lastChar == '}') { - nodeList->push_back(parsed.baseNode); - parsed.doDelete = false; - } + std::string exprStr = input.substr(startPos, count); + + // Parse expression and add to nodes + std::vector tokens; + Lexer::LexString(exprStr, parser->context, tokens, line, col); + ParseResult parsed = Parser::ParseTokensExpression(parser->context, &tokens, line, col); + if (parsed.errors.size() != 0) + parser->errors.insert(parser->errors.end(), parsed.errors.begin(), parsed.errors.end()); + else + { + nodeList->push_back(parsed.baseNode); + parsed.doDelete = false; + } - // Also add the proper string representation - ss << "${" << interpCount++ << "}"; - line = tempLine; - col = tempCol + 1; + // Also add the proper string representation + ss << "${" << interpCount++ << "}"; + line = tempLine; + col = tempCol + 1; + } + else + parser->errors.push_back({ ParseError::ErrorType::ExpectedTokenButEOF, (uint32_t) tempLine, (uint32_t) tempCol, "}" }); } } else