Skip to content

Commit

Permalink
[CPU] Throw when ScatterNDUpdate indices are out of bounds (#27483)
Browse files Browse the repository at this point in the history
Instead of corrupting the memory.
To align the behavior with the documentation.

### Tickets:
 - 154239
  • Loading branch information
EgorDuplensky authored Nov 27, 2024
1 parent cccd27b commit 4c4fb48
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 15 deletions.
13 changes: 13 additions & 0 deletions src/plugins/intel_cpu/src/nodes/scatter_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ void ScatterUpdate::scatterNDUpdate(const MemoryPtr& mem_data,
uint8_t* update = mem_updates->getDataAs<uint8_t>();
uint8_t* dstData = mem_data->getDataAs<uint8_t>();
const auto& srcDataDim = getParentEdgeAt(DATA_ID)->getMemory().getStaticDims();
const auto elementsCount = getParentEdgeAt(DATA_ID)->getMemory().getShape().getElementsCount();
const auto& indicesDim = getParentEdgeAt(INDICES_ID)->getMemory().getStaticDims();
size_t indicesRank = indicesDim.size();

Expand All @@ -1004,8 +1005,14 @@ void ScatterUpdate::scatterNDUpdate(const MemoryPtr& mem_data,
}
dstOffset += idxValue * srcBlockND[i + 1];
}

// Exception must be thrown according to the specification
CPU_NODE_ASSERT(dstOffset < elementsCount,
" indices contain values that points to non-existing data tensor element");

dstOffset *= dataSize;
size_t updateOffset = tupleIdx * sizeToUpdate;

cpu_memcpy(dstData + dstOffset, update + updateOffset, sizeToUpdate);
});
}
Expand All @@ -1020,6 +1027,7 @@ void ScatterUpdate::scatterNDUpdate(const MemoryPtr& mem_data,
DataType* update = mem_updates->getDataAs<DataType>();
DataType* dstData = mem_data->getDataAs<DataType>();
const auto& srcDataDim = getParentEdgeAt(DATA_ID)->getMemory().getStaticDims();
const auto elementsCount = getParentEdgeAt(DATA_ID)->getMemory().getShape().getElementsCount();
const auto& indicesDim = getParentEdgeAt(INDICES_ID)->getMemory().getStaticDims();
const auto indicesRank = indicesDim.size();

Expand All @@ -1041,6 +1049,11 @@ void ScatterUpdate::scatterNDUpdate(const MemoryPtr& mem_data,
}
dstOffset += idxValue * srcBlockND[i + 1];
}

// Exception must be thrown according to the specification
CPU_NODE_ASSERT(dstOffset < elementsCount,
" indices contain values that points to non-existing data tensor element");

const auto updateOffset = tupleIdx * sizeToUpdate;
DataType* dstDataWithOffset = dstData + dstOffset;
const DataType* updateWithOffset = update + updateOffset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ using IndicesValues = std::vector<std::int64_t>;
struct ScatterNDUpdateLayerParams {
ScatterNDUpdateShapes inputShapes;
IndicesValues indicesValues;
bool exceptionExpected;
};

using scatterUpdateParams = std::tuple<ScatterNDUpdateLayerParams,
Expand All @@ -32,6 +33,7 @@ class ScatterNDUpdateLayerCPUTest : public testing::WithParamInterface<scatterUp
std::tie(scatterParams, inputPrecision, idxPrecision) = obj.param;
const auto inputShapes = scatterParams.inputShapes;
const auto indicesValues = scatterParams.indicesValues;
const auto exceptionExpected = scatterParams.exceptionExpected;

std::ostringstream result;
result << inputPrecision << "_IS=";
Expand All @@ -46,7 +48,8 @@ class ScatterNDUpdateLayerCPUTest : public testing::WithParamInterface<scatterUp
}
result << ")_";
}
result << "indices_values=" << ov::test::utils::vec2str(indicesValues) << "_idx_precision=" << idxPrecision;
result << "indices_values=" << ov::test::utils::vec2str(indicesValues) << "_idx_precision=" << idxPrecision << "_";
result << "exception_expected=" << exceptionExpected;
return result.str();
}

Expand Down Expand Up @@ -98,6 +101,7 @@ class ScatterNDUpdateLayerCPUTest : public testing::WithParamInterface<scatterUp
std::tie(scatterParams, inputPrecision, idxPrecision) = this->GetParam();
const auto inputShapes = scatterParams.inputShapes;
const auto indicesValues = scatterParams.indicesValues;
const auto exceptionExpected = scatterParams.exceptionExpected;

init_input_shapes(inputShapes);
selectedType = makeSelectedTypeStr("unknown", inputPrecision);
Expand All @@ -115,6 +119,13 @@ class ScatterNDUpdateLayerCPUTest : public testing::WithParamInterface<scatterUp

ov::ParameterVector allParams{dataParams[0], indicesParam, dataParams[1]};
function = makeNgraphFunction(inputPrecision, allParams, scatter, "ScatterNDUpdateLayerCPUTest");

if (exceptionExpected) {
set_callback_exception([](const std::exception& exp) {
// do nothing, exception is throw as expected
(void) exp;
});
}
}
};

Expand All @@ -130,26 +141,46 @@ const std::vector<ScatterNDUpdateLayerParams> scatterParams = {
{{2, 2, 1}, {{2, 2, 1}, {2, 2, 1}, {2, 2, 1}}},
{{-1, -1, -1, -1, -1, -1}, {{2, 2, 9, 10, 9, 10}, {2, 2, 1, 11, 2, 5}, {2, 2, 15, 8, 1, 7}}},
},
IndicesValues{5, 6, 2, 8}},
ScatterNDUpdateLayerParams{ScatterNDUpdateShapes{{{-1, -1, -1, -1}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{-1, -1}, {{2, 11}, {2, 12}, {2, 8}}}},
IndicesValues{0, 1, 1, 2, 2, 2}},
IndicesValues{5, 6, 2, 8}
},
ScatterNDUpdateLayerParams{
ScatterNDUpdateShapes{{{{3, 10}, -1, {3, 9}, -1}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}},
ScatterNDUpdateShapes{
{{-1, -1, -1, -1}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{-1, -1}, {{2, 11}, {2, 12}, {2, 8}}}
},
IndicesValues{0, 1, 1, 2, 2, 2}
},
ScatterNDUpdateLayerParams{
ScatterNDUpdateShapes{
{{{3, 10}, -1, {3, 9}, -1}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}
},
IndicesValues{0, 1, 1, 2, 2, 2}},
ScatterNDUpdateLayerParams{
ScatterNDUpdateShapes{{{{3, 10}, {4, 11}, {3, 9}, {8, 15}}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}},
ScatterNDUpdateShapes{
{{{3, 10}, {4, 11}, {3, 9}, {8, 15}}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}
},
IndicesValues{0, 1, 1, 2, 2, 2}},
ScatterNDUpdateLayerParams{
ScatterNDUpdateShapes{{{{3, 10}, {4, 11}, {3, 9}, {8, 15}}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}},
ScatterNDUpdateShapes{
{{{3, 10}, {4, 11}, {3, 9}, {8, 15}}, {{10, 9, 9, 11}, {7, 5, 3, 12}, {3, 4, 9, 8}}},
{{2, 3}, {{2, 3}, {2, 3}, {2, 3}}},
{{{2, 4}, -1}, {{2, 11}, {2, 12}, {2, 8}}}},
IndicesValues{-1, -1, -1, -2, -2, -2}},
// out of bounds indices
ScatterNDUpdateLayerParams{
ScatterNDUpdateShapes{
{{}, {{4, 8, 64, 1}}},
{{}, {{1}}},
{{}, {{8, 64, 1}}}
},
IndicesValues{4}, // index is out of bounds
true
},
};

const std::vector<ElementType> inputPrecisions = {
Expand Down

0 comments on commit 4c4fb48

Please sign in to comment.