Mkulakow/fixes - #4455
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens request-to-tensor conversion and custom node behaviors, primarily by adding stricter validation for mixed image batches and malformed KFS BYTES payloads, plus a fix to cap object-detection outputs to max_output_batch.
Changes:
- Reject mixed-channel image batches when converting native file inputs (and add coverage for ranged channel dimensions).
- Harden KFS BYTES/string parsing against overflow/wrap-style malformed length prefixes.
- Fix
model_zoo_intel_object_detectionto resize all output vectors consistently when capping tomax_output_batch, and add a regression test.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/test/tensor_conversion_test.cpp |
Adds negative tests for mixed-channel batches and malformed BYTES payloads (needs robust file-open/read checks). |
src/test/node_library_manager_test.cpp |
Adds regression test asserting object-detection node caps outputs to max_output_batch. |
src/tensor_conversion.hpp |
Adds mixed-channel-in-batch validation during native file input conversion. |
src/tensor_conversion.cpp |
Adds empty-batch guard and size-consistency check in createTensorFromMats. |
src/tensor_conversion_common.cpp |
Mirrors createTensorFromMats hardening in the common implementation. |
src/kfs_frontend/kfs_utils.cpp |
Reworks BYTES parsing to avoid accumulator overflow and out-of-bounds reads (uses memcpy + bounds checks). |
src/filesystem/s3filesystem.cpp |
Changes default scheme handling for custom S3 endpoints (potential behavior break for endpoints without an explicit scheme). |
src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp |
Ensures all output vectors are resized consistently when capping results. |
src/custom_nodes/common/custom_node_library_internal_manager.hpp |
Fixes get_buffer() to avoid returning undersized queue buffers and avoids use of an uninitialized out-pointer. |
Suppressed comments (1)
src/test/tensor_conversion_test.cpp:629
- Same issue here: the test assumes grayscale.jpg can be opened and read; on failure, tellg() may return -1 and the test will allocate an enormous buffer.
std::ifstream grayscaleDataFile;
grayscaleDataFile.open(getGenericFullPathForSrcTest("/ovms/src/test/binaryutils/grayscale.jpg"), std::ios::binary);
grayscaleDataFile.seekg(0, std::ios::end);
size_t grayscaleFilesize = grayscaleDataFile.tellg();
grayscaleDataFile.seekg(0);
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| std::ifstream grayscaleDataFile; | ||
| grayscaleDataFile.open(getGenericFullPathForSrcTest("/ovms/src/test/binaryutils/grayscale.jpg"), std::ios::binary); | ||
| grayscaleDataFile.seekg(0, std::ios::end); | ||
| size_t grayscaleFilesize = grayscaleDataFile.tellg(); | ||
| grayscaleDataFile.seekg(0); | ||
| std::unique_ptr<char[]> grayscaleImageBytes(new char[grayscaleFilesize]); | ||
| grayscaleDataFile.read(grayscaleImageBytes.get(), grayscaleFilesize); |
| config.endpointOverride = Aws::String(host_name + ":" + host_port); | ||
| config.scheme = Aws::Http::Scheme::HTTP; | ||
| config.scheme = Aws::Http::Scheme::HTTPS; | ||
| } | ||
| if (s3_endpoint != nullptr) { | ||
| std::string endpoint(s3_endpoint); | ||
| if (endpoint.rfind("http://") != std::string::npos) { | ||
| config.scheme = Aws::Http::Scheme::HTTPS; | ||
| if (endpoint.rfind("http://", 0) == 0) { | ||
| endpoint = endpoint.substr(7); | ||
| config.scheme = Aws::Http::Scheme::HTTP; | ||
| } else if (endpoint.rfind("https://", 0) == 0) { | ||
| endpoint = endpoint.substr(8); | ||
| } | ||
| config.endpointOverride = Aws::String(endpoint.c_str()); | ||
| config.scheme = Aws::Http::Scheme::HTTP; | ||
| } |
There was a problem hiding this comment.
Does it pass our minio validation ? Should we update documentation ?
| ov::Tensor tensor(precision, shape); | ||
| char* ptr = (char*)tensor.data(); | ||
| const size_t firstImageSizeBytes = images[0].total() * images[0].elemSize(); | ||
| for (cv::Mat image : images) { |
| ov::Tensor tensor(precision, shape); | ||
| char* ptr = (char*)tensor.data(); | ||
| const size_t firstImageSizeBytes = images[0].total() * images[0].elemSize(); | ||
| for (cv::Mat image : images) { |
| if (headersLength > buffer->size()) { | ||
| break; | ||
| } | ||
| if (totalStringsLength > buffer->size() - headersLength) { | ||
| break; | ||
| } | ||
| const size_t currentOffset = totalStringsLength + headersLength; | ||
| if (buffer->size() - currentOffset < sizeof(uint32_t)) { | ||
| break; | ||
| } |
There was a problem hiding this comment.
Should we simply break from those conditions? Not return error?
rasapala
left a comment
There was a problem hiding this comment.
Copilot had good suggestions.
🛠 Summary
JIRA/Issue if applicable.
Describe the changes.
🧪 Checklist
``