From 7264d519af881284e23193d3a6f2ca4186779f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Szczepaniak?= Date: Wed, 29 Apr 2020 19:47:05 +0100 Subject: Fix null ptr dereference in squeeze cpu implementation. Squeeze, when used on a single-value tensor with 1s in each dimension, will result in zero-sized tensor without dimensions. This change fixes it, by making its output a tensor of size [1]. Bug: 155238914 Test: squeeze_b155238914.mod.py run on coral. Change-Id: Ia5bf655c647084d9fa094ae8a2048917a8237b81 --- nn/common/operations/Squeeze.cpp | 11 ++- .../spec_V1_2/squeeze_b155238914.example.cpp | 87 ++++++++++++++++++++++ .../test/specs/V1_2/squeeze_b155238914.mod.py | 32 ++++++++ 3 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 nn/runtime/test/generated/spec_V1_2/squeeze_b155238914.example.cpp create mode 100644 nn/runtime/test/specs/V1_2/squeeze_b155238914.mod.py (limited to 'nn') diff --git a/nn/common/operations/Squeeze.cpp b/nn/common/operations/Squeeze.cpp index 977856d2d..276461d1e 100644 --- a/nn/common/operations/Squeeze.cpp +++ b/nn/common/operations/Squeeze.cpp @@ -110,9 +110,14 @@ bool prepare(IOperationExecutionContext* context) { // Sets output dimensions. std::vector outDims(numInputDims - numDimsSqueezed); - for (int32_t inIdx = 0, outIdx = 0; inIdx < numInputDims; ++inIdx) { - if (!shouldSqueeze[inIdx]) { - outDims[outIdx++] = getSizeOfDimension(inputShape, inIdx); + if (numInputDims == numDimsSqueezed) { + // Handle edge case where squeeze removes all dimensions. + outDims.push_back(1); + } else { + for (int32_t inIdx = 0, outIdx = 0; inIdx < numInputDims; ++inIdx) { + if (!shouldSqueeze[inIdx]) { + outDims[outIdx++] = getSizeOfDimension(inputShape, inIdx); + } } } Shape outputShape(inputShape); diff --git a/nn/runtime/test/generated/spec_V1_2/squeeze_b155238914.example.cpp b/nn/runtime/test/generated/spec_V1_2/squeeze_b155238914.example.cpp new file mode 100644 index 000000000..c2fad450f --- /dev/null +++ b/nn/runtime/test/generated/spec_V1_2/squeeze_b155238914.example.cpp @@ -0,0 +1,87 @@ +// Generated from squeeze_b155238914.mod.py +// DO NOT EDIT +// clang-format off +#include "TestHarness.h" +using namespace test_helper; + +namespace generated_tests::squeeze_b155238914 { + +const TestModel& get_test_model() { + static TestModel model = { + .expectFailure = false, + .expectedMultinomialDistributionTolerance = 0, + .isRelaxed = false, + .main = { + .inputIndexes = {0}, + .operands = {{ // op0 + .channelQuant = {}, + .data = TestBuffer::createFromVector({0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}), + .dimensions = {9, 1, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_INPUT, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { // op1 + .channelQuant = {}, + .data = TestBuffer::createFromVector({0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}), + .dimensions = {9, 1, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::SUBGRAPH_OUTPUT, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { // op5 + .channelQuant = {}, + .data = TestBuffer::createFromVector({0.0f}), + .dimensions = {1, 1, 1}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::CONSTANT_COPY, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }, { // op7 + .channelQuant = {}, + .data = TestBuffer::createFromVector({}), + .dimensions = {0}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::NO_VALUE, + .numberOfConsumers = 1, + .scale = 0.0f, + .type = TestOperandType::TENSOR_INT32, + .zeroPoint = 0 + }, { // op8 + .channelQuant = {}, + .data = TestBuffer::createFromVector({}), + .dimensions = {}, + .isIgnored = false, + .lifetime = TestOperandLifeTime::TEMPORARY_VARIABLE, + .numberOfConsumers = 0, + .scale = 0.0f, + .type = TestOperandType::TENSOR_FLOAT32, + .zeroPoint = 0 + }}, + .operations = {{ + .inputs = {0}, + .outputs = {1}, + .type = TestOperationType::FLOOR + }, { + .inputs = {2, 3}, + .outputs = {4}, + .type = TestOperationType::SQUEEZE + }}, + .outputIndexes = {1} + }, + .minSupportedVersion = TestHalVersion::V1_2, + .referenced = {} + }; + return model; +} + +const auto dummy_test_model = TestModelManager::get().add("squeeze_b155238914", get_test_model()); + +} // namespace generated_tests::squeeze_b155238914 + diff --git a/nn/runtime/test/specs/V1_2/squeeze_b155238914.mod.py b/nn/runtime/test/specs/V1_2/squeeze_b155238914.mod.py new file mode 100644 index 000000000..70e41c6d3 --- /dev/null +++ b/nn/runtime/test/specs/V1_2/squeeze_b155238914.mod.py @@ -0,0 +1,32 @@ +# +# Copyright (C) 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Model operands +op0 = Input("op0", ["TENSOR_FLOAT32", [9, 1, 1]]) +op1 = Output("op1", ["TENSOR_FLOAT32", [9, 1, 1]]) +op5 = Parameter("op5", ["TENSOR_FLOAT32", [1, 1, 1]], [0]) +op7 = Parameter("op7", ["TENSOR_INT32", [0]], value=None) # omitted +op8 = Internal("op8", ["TENSOR_FLOAT32", []]) + +# Model operations +model = Model() +model.Operation("FLOOR", op0).To(op1) +model.Operation("SQUEEZE", op5, op7).To(op8) + +# Example +Example({ + op0: [0, 0, 0, 0, 0, 0, 0, 0, 0], + op1: [0, 0, 0, 0, 0, 0, 0, 0, 0], +}, model=model).DisableLifeTimeVariation() -- cgit v1.2.3