Skip to content

Fix v1 v2 v3 REST endpoint parsers#4167

Open
dkalinowski wants to merge 5 commits intomainfrom
fix-parser
Open

Fix v1 v2 v3 REST endpoint parsers#4167
dkalinowski wants to merge 5 commits intomainfrom
fix-parser

Conversation

@dkalinowski
Copy link
Copy Markdown
Collaborator

🛠 Summary

CVS-185843

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the v1/v2/v3 REST JSON parsing paths against excessively deep nesting by switching to RapidJSON’s iterative parsing mode and introducing explicit maximum nesting-depth limits, along with unit tests covering the new behavior.

Changes:

  • Use rapidjson::kParseIterativeFlag for REST JSON parsing (TFS + KFS + v3 HTTP payload).
  • Add maximum nesting-depth enforcement for TFS/KFS tensor array parsing and v3 OpenAI JSON body validation.
  • Add tests ensuring deeply nested inputs are rejected and shallow nesting remains accepted.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/rest_parser.cpp Adds MAX_NESTING_DEPTH, enforces depth during array parsing, and switches TFS/KFS parsing to iterative RapidJSON parse.
src/rest_parser.hpp Extends KFSRestParser::parseData signature to carry recursion depth.
src/http_rest_api_handler.cpp Adds a JSON depth check for v3 JSON payloads and switches parsing to iterative RapidJSON parse.
src/test/tfs_rest_parser_row_test.cpp Adds nesting-depth tests for TFS row format.
src/test/tfs_rest_parser_column_test.cpp Adds nesting-depth tests for TFS column format.
src/test/kfs_rest_parser_test.cpp Adds nesting-depth tests for KFS REST input parsing.
src/test/http_openai_handler_test.cpp Adds tests validating v3 OpenAI handler behavior for excessive JSON nesting.

Comment thread src/rest_parser.cpp Outdated
Comment thread src/rest_parser.cpp
Comment on lines +32 to +33
static constexpr int MAX_NESTING_DEPTH = 100;

Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_NESTING_DEPTH is introduced here as a TU-local magic number (100). The same limit is also hard-coded for OpenAI JSON handling (MAX_JSON_NESTING_DEPTH in http_rest_api_handler.cpp). Consider centralizing this limit (or at least reusing a shared constant) to avoid the two code paths drifting to different effective limits over time.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont like this idea, we might have different limit for different API in future

Comment thread src/test/http_openai_handler_test.cpp Outdated
Comment thread src/http_rest_api_handler.cpp Outdated
Comment thread src/http_rest_api_handler.cpp Outdated
return Status(StatusCode::JSON_INVALID, "JSON body must be an object");
}

if (jsonDepthExceedsLimit(*parsedJson)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this placement? Not at the very beginning or somewhere near the end of processing?
Do we need to do it before the first time we do a lookup?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed manual depth calculation, used SAX filter instead

Comment thread src/test/kfs_rest_parser_test.cpp Outdated
Comment on lines +1029 to +1045
TEST_F(KFSRestParserTest, NestingDepthExceeded_FP32) {
std::string request = R"({"inputs":[{"name":"input0","shape":[1],"datatype":"FP32","data":)" + makeNestedArrayJson(200) + "}]}";
auto status = parser.parse(request.c_str());
EXPECT_EQ(status, StatusCode::REST_COULD_NOT_PARSE_INPUT);
}

TEST_F(KFSRestParserTest, NestingDepthExceeded_BYTES) {
std::string request = R"({"inputs":[{"name":"input0","shape":[1],"datatype":"BYTES","data":)" + makeNestedArrayJson(200) + "}]}";
auto status = parser.parse(request.c_str());
EXPECT_EQ(status, StatusCode::REST_COULD_NOT_PARSE_INPUT);
}

TEST_F(KFSRestParserTest, NestingDepthExceeded_INT32) {
std::string request = R"({"inputs":[{"name":"input0","shape":[1],"datatype":"INT32","data":)" + makeNestedArrayJson(200) + "}]}";
auto status = parser.parse(request.c_str());
EXPECT_EQ(status, StatusCode::REST_COULD_NOT_PARSE_INPUT);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one type would be sufficient?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants