diff --git a/Compiler/src/Compiler.cpp b/Compiler/src/Compiler.cpp index dcda5afd..ec0569c6 100644 --- a/Compiler/src/Compiler.cpp +++ b/Compiler/src/Compiler.cpp @@ -14,6 +14,7 @@ #include #include +#include #include LUAU_FASTINTVARIABLE(LuauCompileLoopUnrollThreshold, 25) @@ -1495,14 +1496,21 @@ struct Compiler formatString += "%s"; } - std::string& formatStringRef = interpFormatStrings.emplace_back(formatString); + auto formatStringSize = formatString.size(); - AstArray formatStringArray{formatStringRef.data(), formatStringRef.size()}; + // We can't use formatStringRef.data() directly, because short strings don't have their data + // pinned in memory, so when interpFormatStrings grows, these pointers will move and become invalid. + std::shared_ptr formatStringPtr(new char[formatStringSize]); + memcpy(formatStringPtr.get(), formatString.data(), formatStringSize); + + auto formatStringPtrRef = interpFormatStrings.emplace_back(formatStringPtr); + AstArray formatStringArray{formatStringPtrRef.get(), formatStringSize}; int32_t formatStringIndex = bytecode.addConstantString(sref(formatStringArray)); if (formatStringIndex < 0) CompileError::raise(expr->location, "Exceeded constant limit; simplify the code to compile"); + bytecode.emitABC(LOP_LOADK, target, formatStringIndex, 0); // INTERP CODE REVIEW: Why do I need this? @@ -1513,9 +1521,7 @@ struct Compiler RegScope rs(this); for (AstExpr* expression : expr->expressions) - { compileExprAuto(expression, rs); - } BytecodeBuilder::StringRef formatMethod = sref(AstName("format")); @@ -3630,7 +3636,7 @@ struct Compiler std::vector loops; std::vector inlineFrames; std::vector captures; - std::vector interpFormatStrings; + std::vector> interpFormatStrings; }; void compileOrThrow(BytecodeBuilder& bytecode, const ParseResult& parseResult, const AstNameTable& names, const CompileOptions& inputOptions) diff --git a/tests/conformance/stringinterp.lua b/tests/conformance/stringinterp.lua index fbccfec1..665250a9 100644 --- a/tests/conformance/stringinterp.lua +++ b/tests/conformance/stringinterp.lua @@ -9,7 +9,7 @@ end assertEq(`hello {"world"}`, "hello world") --- assertEq(`2 + 2 = {2 + 2}`, "2 + 2 = 4") +assertEq(`2 + 2 = {2 + 2}`, "2 + 2 = 4") -- assertEq(`{1} {2} {3} {4} {5} {6} {7}`, "1 2 3 4 5 6 7")