Skip to content

Commit b83813e

Browse files
authored
[core] Check constant byte on construction from aligned buffer (#34463)
### Details: - The Constant node created from AlignedBuffer validates buffer size and byte size as result of shape and precision and not allo to create the node if sizes not same. ### Tickets: - CVS-182180 --------- Signed-off-by: Pawel Raasz <pawel.raasz@intel.com>
1 parent 8ab19a9 commit b83813e

File tree

5 files changed

+40
-27
lines changed

5 files changed

+40
-27
lines changed

src/core/src/op/constant.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,14 @@ Constant::Constant(const element::Type& type, const Shape& shape, const std::sha
302302
m_shape(shape),
303303
m_byte_strides(calc_byte_strides(m_shape, m_element_type)),
304304
m_data(data) {
305+
const auto constant_size = ov::util::get_memory_size_safe(m_element_type, m_shape);
306+
OPENVINO_ASSERT(constant_size, "Cannot calculate byte size for type: ", m_element_type, " and shape: ", m_shape);
307+
const auto data_size = ((*constant_size > 0) && data) ? data->size() : 0;
308+
OPENVINO_ASSERT(*constant_size == data_size,
309+
"The Constant byte size and input data byte size not same: ",
310+
*constant_size,
311+
" != ",
312+
data_size);
305313
constructor_validate_and_infer_types();
306314
}
307315

@@ -383,7 +391,6 @@ std::string Constant::convert_value_to_string(size_t index) const {
383391
}
384392

385393
size_t Constant::get_byte_size() const {
386-
// Returns 0 when shape is "empty" (equals 0).
387394
// TODO: refactor shape_size(m_shape) calculations and store it as a member.
388395
return shape_size(m_shape) ? m_data->size() : 0;
389396
}

src/core/tests/constant.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,6 +2663,7 @@ TEST(constant, hold_shared_memory_different_precision) {
26632663
EXPECT_EQ(c.get_data_ptr(), storage.data());
26642664
EXPECT_EQ(c.get_vector<uint8_t>(), std::vector<uint8_t>({1, 0, 0, 0, 2, 0}));
26652665
EXPECT_EQ(c.cast_vector<uint8_t>(), std::vector<uint8_t>({1, 0, 0, 0, 2, 0}));
2666+
EXPECT_EQ(c.get_byte_size(), 6);
26662667
}
26672668

26682669
TEST(constant, own_shared_memory) {
@@ -2865,6 +2866,17 @@ TEST(constant, dynamic_type_cast_vector_throws) {
28652866
EXPECT_THROW(c.cast_vector<int64_t>(), ov::Exception);
28662867
}
28672868

2869+
TEST(constant, create_with_incorrect_buffer_size_or_shape_and_precision) {
2870+
auto buffer = std::make_shared<ov::AlignedBuffer>(100);
2871+
EXPECT_THROW(std::ignore = ov::op::v0::Constant(element::u8, Shape{10}, buffer), ov::Exception);
2872+
}
2873+
2874+
TEST(constant, create_with_zero_dim_shape) {
2875+
auto c = ov::op::v0::Constant(element::u8, Shape{10, 0});
2876+
2877+
EXPECT_EQ(c.get_byte_size(), 0);
2878+
}
2879+
28682880
} // namespace test
28692881
} // namespace ov
28702882

src/core/tests/weight_sharing_util_test.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ const auto create_test_model_weights_from_file = [](const std::filesystem::path&
8484
w_buff->size() / 2,
8585
w_buff);
8686

87-
auto param = std::make_shared<Parameter>(ov::element::f32, Shape{2, 200});
88-
auto add = std::make_shared<Add>(param, std::make_shared<Constant>(element::f32, Shape{1, 200}, w1));
89-
add = std::make_shared<Add>(add, std::make_shared<Constant>(element::f32, Shape{1, 200}, w2));
87+
auto param = std::make_shared<Parameter>(ov::element::f32, Shape{2, 2000});
88+
auto add = std::make_shared<Add>(param, std::make_shared<Constant>(element::f32, Shape{1, 2000}, w1));
89+
add = std::make_shared<Add>(add, std::make_shared<Constant>(element::f32, Shape{1, 2000}, w2));
9090
return std::make_shared<ov::Model>(add->outputs(), "Test model weight from file");
9191
};
9292

@@ -102,7 +102,7 @@ TEST_F(WeightShareExtensionTest, get_constant_id_with_descriptor) {
102102
create_test_weights_file(w_path);
103103
auto w_buffer = ov::load_mmap_object(w_path);
104104
auto w1 = std::make_shared<SharedBuffer<std::shared_ptr<ov::MappedMemory>>>(w_buffer->data() + 200,
105-
w_buffer->size() - 200,
105+
sizeof(float) * 200,
106106
w_buffer);
107107
auto constant = Constant(element::f32, Shape{200}, w1);
108108

@@ -117,7 +117,7 @@ TEST_F(WeightShareExtensionTest, get_constant_source_buffer_check_id) {
117117

118118
auto w_buffer = ov::load_mmap_object(w_path);
119119
auto w1 = std::make_shared<SharedBuffer<std::shared_ptr<ov::MappedMemory>>>(w_buffer->data() + 200,
120-
w_buffer->size() - 200,
120+
sizeof(float) * 200,
121121
w_buffer);
122122
auto constant = Constant(element::f32, Shape{200}, w1);
123123

src/frontends/onnx/frontend/src/core/tensor.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -448,25 +448,19 @@ std::shared_ptr<ov::op::v0::Constant> Tensor::get_ov_constant() const {
448448
reinterpret_cast<size_t>(m_tensor_place->get_data()),
449449
m_tensor_place->get_data_size())
450450
: detail::TensorExternalData(*m_tensor_proto);
451+
452+
std::shared_ptr<ov::AlignedBuffer> constant_buffer;
451453
if (ext_data.data_location() == detail::ORT_MEM_ADDR) {
452-
constant = std::make_shared<ov::op::v0::Constant>(ov_type, m_shape, ext_data.load_external_mem_data());
454+
constant_buffer = ext_data.load_external_mem_data();
453455
} else if (m_mmap_cache) {
454-
constant = std::make_shared<ov::op::v0::Constant>(
455-
ov_type,
456-
m_shape,
457-
ext_data.load_external_mmap_data(m_model_dir.string(), m_mmap_cache));
456+
constant_buffer = ext_data.load_external_mmap_data(m_model_dir.string(), m_mmap_cache);
458457
} else {
459-
constant = std::make_shared<ov::op::v0::Constant>(ov_type,
460-
m_shape,
461-
ext_data.load_external_data(m_model_dir.string()));
462-
}
463-
// ext_data.size() might be zero, need to recalc by using info about actually red data (for byte-size)
464-
element_count = constant->get_byte_size() / ov_type.size();
465-
if (ov::element::is_nibble_type(ov_type)) {
466-
element_count *= 2; // Each byte contains 2 data items, so byte size must be multiplicated
458+
constant_buffer = ext_data.load_external_data(m_model_dir.string());
467459
}
468-
if (element_count != ov::shape_size(m_shape) ||
469-
(ext_data.size() != 0 && constant->get_byte_size() != ext_data.size())) {
460+
461+
try {
462+
constant = std::make_shared<ov::op::v0::Constant>(ov_type, m_shape, constant_buffer);
463+
} catch (const ov::Exception&) {
470464
throw error::invalid_external_data(
471465
"The size of the external data file does not match the byte size of an initializer '" + get_name() +
472466
"' in the model");

src/frontends/onnx/tests/onnx_reader_external_data.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//
44

5-
#include <gtest/gtest.h>
5+
#include <gmock/gmock.h>
66
#include <onnx/onnx_pb.h>
77

88
#include <algorithm>
@@ -23,6 +23,7 @@ using namespace std;
2323
using namespace ov;
2424
using namespace frontend;
2525
using namespace frontend::onnx::tests;
26+
using testing::AnyOf, testing::HasSubstr;
2627

2728
// API 2.0 tests
2829
class OnnxFeMmapFixture : public ::testing::TestWithParam<bool> {};
@@ -120,11 +121,10 @@ TEST_P(OnnxFeMmapFixture, onnx_external_data_incorrect_size_exception) {
120121
const auto model = core.read_model(path);
121122
FAIL() << "Incorrect size of external data not detected";
122123
} catch (const Exception& ex) {
123-
EXPECT_PRED_FORMAT2(
124-
testing::IsSubstring,
125-
string(
126-
"The size of the external data file does not match the byte size of an initializer 'A' in the model"),
127-
ex.what());
124+
EXPECT_THAT(
125+
ex.what(),
126+
HasSubstr(
127+
"The size of the external data file does not match the byte size of an initializer 'A' in the model"));
128128
} catch (...) {
129129
FAIL() << "Importing onnx model failed for unexpected reason";
130130
}

0 commit comments

Comments
 (0)