Fix Json lexeme trying to allocate a string with a huge size due to underflow (#9539)

This commit is contained in:
yein
2025-12-19 13:29:01 -08:00
committed by GitHub
parent ee74e2d50c
commit 9720da2c68
3 changed files with 25 additions and 3 deletions

View File

@@ -34,7 +34,7 @@ enum JsonType {
COLUMN,
};
class JsonLexeme final: public Lexeme<JsonType > {
class JsonLexeme final: public Lexeme<JsonType> {
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 };
}

View File

@@ -287,8 +287,8 @@ utils::Status MaterialParser::parseMaterialAsJSON(const char* buffer, size_t siz
JsonishParser parser(jlexer.getLexemes());
std::unique_ptr<JsonishObject> 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()) {

View File

@@ -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();