diff --git a/libs/filament-matp/src/JsonishLexeme.h b/libs/filament-matp/src/JsonishLexeme.h index ed130aab66..4bece4129f 100644 --- a/libs/filament-matp/src/JsonishLexeme.h +++ b/libs/filament-matp/src/JsonishLexeme.h @@ -34,7 +34,7 @@ enum JsonType { COLUMN, }; -class JsonLexeme final: public Lexeme { +class JsonLexeme final: public Lexeme { public: static const char* getTypeString(JsonType type) { switch (type) { @@ -63,6 +63,13 @@ public: } const char *start = (*mStart == '"') ? mStart + 1 : mStart; const char *end = (*mEnd == '"') ? mEnd - 1 : mEnd; + // Edge case: If the string only contains a single double-quote, the end can be before the + // start, which causes Lexeme::getStringValue to allocate a string with a large size, since + // it under flows. So we don't trim in this case, though this will fail to parse. + if (start > end) { + start = mStart; + end = mEnd; + } return { mType, start, end, mLineNumber, mPosition }; } diff --git a/libs/filament-matp/src/MaterialParser.cpp b/libs/filament-matp/src/MaterialParser.cpp index 06815db190..ad0127269f 100644 --- a/libs/filament-matp/src/MaterialParser.cpp +++ b/libs/filament-matp/src/MaterialParser.cpp @@ -287,8 +287,8 @@ utils::Status MaterialParser::parseMaterialAsJSON(const char* buffer, size_t siz JsonishParser parser(jlexer.getLexemes()); std::unique_ptr json = parser.parse(); - if (json == nullptr) { - return utils::Status::internal("Could not parse JSON material file"); + if (json == nullptr || !parser.getParseStatus().isOk()) { + return parser.getParseStatus(); } for (auto& entry : json->getEntries()) { diff --git a/libs/filament-matp/tests/test_matp.cpp b/libs/filament-matp/tests/test_matp.cpp index a8b5bb97d3..d9262877cb 100644 --- a/libs/filament-matp/tests/test_matp.cpp +++ b/libs/filament-matp/tests/test_matp.cpp @@ -332,6 +332,21 @@ TEST_F(MaterialLexer, JsonMaterialParserInvalidInputReturnsError) { EXPECT_EQ(root, nullptr); } +TEST_F(MaterialLexer, JsonMaterialParserSingleDoubleQuoteDoesntCrash) { + static std::string singleDoubleQuote = R"( + material: { + name: ", + } + )"; + matp::MaterialParser parser; + TestMaterialParser testParser(parser); + filamat::MaterialBuilder unused; + utils::Status result = testParser.parseMaterialAsJSON( + singleDoubleQuote.c_str(), singleDoubleQuote.size(), unused); + + EXPECT_EQ(result.getCode(), utils::StatusCode::INVALID_ARGUMENT); +} + int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();