[CVS-182698] Fix tensor import failure caused by read-only blob tensor#971
[CVS-182698] Fix tensor import failure caused by read-only blob tensor#971n1harika merged 3 commits intoovep-developfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes OpenVINO EP compiled-model blob import failures by changing how native blob tensors are constructed so ov::Core::import_model() can access the underlying blob bytes when the blob comes from a file-mapped tensor.
Changes:
- Build native blob tensors from an explicit
u8pointer + shape instead of creating a sub-tensor view into the mapped file tensor. - Use
const_castto pass a mutable pointer to OpenVINO tensor construction for both mapped-file blobs and embedded-vector blobs.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| auto blob_offset = blob_container.serialized_info.file_offset; | ||
| auto blob_size = blob_container.serialized_info.size; | ||
| ov::Coordinate begin{blob_offset}; | ||
| ov::Coordinate end{blob_offset + blob_size}; | ||
| blob_container.tensor = ov::Tensor(mapped_bin_, begin, end); | ||
| const uint8_t* src = mapped_bin_.data<const uint8_t>() + blob_offset; | ||
|
|
||
| blob_container.tensor = ov::Tensor( | ||
| ov::element::u8, | ||
| ov::Shape{blob_size}, | ||
| const_cast<uint8_t*>(src)); |
There was a problem hiding this comment.
src is computed via pointer arithmetic without validating that blob_offset + blob_size stays within the mapped file tensor. If the BSON metadata is corrupt/mismatched (or a truncated external .bin is used), this can create an out-of-bounds pointer and later crash/UB when OpenVINO reads it. Add an ORT_ENFORCE range check against mapped_bin_.get_byte_size() (and also guard against integer overflow) before forming the pointer / tensor.
| const uint8_t* src = mapped_bin_.data<const uint8_t>() + blob_offset; | ||
|
|
||
| blob_container.tensor = ov::Tensor( | ||
| ov::element::u8, | ||
| ov::Shape{blob_size}, | ||
| const_cast<uint8_t*>(src)); | ||
| } else { | ||
| // Create a tensor from embedded data vector | ||
| blob_container.tensor = ov::Tensor( | ||
| ov::element::u8, | ||
| ov::Shape{blob_container.data.size()}, | ||
| blob_container.data.data()); | ||
| const_cast<uint8_t*>(blob_container.data.data())); |
There was a problem hiding this comment.
This introduces const_cast<uint8_t*>(...) to satisfy ov::Tensor's mutable-pointer constructor, but it drops const-safety for memory that may be genuinely read-only (mmap) and makes the intent unclear. Consider matching the existing pattern in ov_shared_context.cc by using a read-only ov::Tensor constructor when OPENVINO_VERSION_AT_LEAST(2026, 0) is available, and only using const_cast on older OpenVINO versions (with an explicit comment that the buffer must not be written).
| ov::element::u8, | ||
| ov::Shape{blob_container.data.size()}, | ||
| blob_container.data.data()); | ||
| const_cast<uint8_t*>(blob_container.data.data())); |
There was a problem hiding this comment.
blob_container.data.data() is already a mutable uint8_t* here, so the const_cast is unnecessary and makes it harder to reason about where const is being removed. Prefer passing blob_container.data.data() directly.
| const_cast<uint8_t*>(blob_container.data.data())); | |
| blob_container.data.data()); |
MayureshV1
left a comment
There was a problem hiding this comment.
@n1harika , Can you please look into CoPilot suggestions and if you prefer to make an implementation change,
b2052b7 to
94eca74
Compare
Fix tensor import failure in OVEP caused by blob tensors being created as read-only views.
Construct the tensor as a mutable pointer so OV core.import_model() can access the blob for file-mapped behavior.