已合并
fix(bounding_box_encode): add validations in geir path and inferdatatype #1182
zhangyiyi创建于 7月27日
fix(bounding_box_encode): add validations in geir path and inferdatatype #1182
已合并
zhangyiyi创建于 7月27日
3 个文件变更+184-4
@@ -0,0 +1,40 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/* Generated By CANNBot */
12+ 
13+/*!
14+ * \file bounding_box_encode_graph_infer.cpp
15+ * \brief BoundingBoxEncode operator graph infer datatype resource
16+ */
17+ 
18+#include "register/op_impl_registry.h"
19+#include "log/log.h"
20+ 
21+namespace ops {
22+using namespace ge;
23+ 
24+static constexpr int64_t IDX_0 = 0;
25+ 
26+// delats.dtype = anchor_box.dtype
27+static ge::graphStatus InferDataType4BoundingBoxEncode(gert::InferDataTypeContext* context)
28+{
29+ OP_LOGD(context->GetNodeName(), "Begin to do InferDataType4BoundingBoxEncode");
30+ 
31+ ge::DataType anchorBoxDtype = context->GetInputDataType(IDX_0);
32+ context->SetOutputDataType(IDX_0, anchorBoxDtype);
33+ 
34+ OP_LOGD(context->GetNodeName(), "End to do InferDataType4BoundingBoxEncode");
35+ return GRAPH_SUCCESS;
36+}
37+ 
38+IMPL_OP(BoundingBoxEncode).InferDataType(InferDataType4BoundingBoxEncode);
39+ 
40+} // namespace ops
@@ -35,6 +35,7 @@ constexpr int64_t NUM_IO_BUFFERS = 3;
35constexpr int64_t NUM_CALC_BUFFERS = 2;35constexpr int64_t NUM_CALC_BUFFERS = 2;
36constexpr int64_t NUM_TOTAL_BUFFERS = 5;36constexpr int64_t NUM_TOTAL_BUFFERS = 5;
37constexpr int64_t BLOCK_ELEM_THRESHOLD = 32768;37constexpr int64_t BLOCK_ELEM_THRESHOLD = 32768;
38+constexpr size_t MEANS_STDS_LEN = 4;
38 39 
39static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context)40static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context)
40{41{
@@ -52,6 +53,11 @@ static ge::graphStatus ParseMeansStds(gert::TilingContext* context, BoundingBoxE
52 const auto* stdsList = attrs->GetListFloat(1);53 const auto* stdsList = attrs->GetListFloat(1);
53 OP_CHECK_IF(meansList == nullptr || stdsList == nullptr, OP_LOGE(context, "means or stds attr is null"),54 OP_CHECK_IF(meansList == nullptr || stdsList == nullptr, OP_LOGE(context, "means or stds attr is null"),
54 return ge::GRAPH_FAILED);55 return ge::GRAPH_FAILED);
56+ // 3a/3b: means and stds length must be exactly 4. Check before reading [0..3] to avoid OOB read.
57+ OP_CHECK_IF(meansList->GetSize() != MEANS_STDS_LEN,
58+ OP_LOGE(context, "means length must be 4, but got %zu", meansList->GetSize()), return ge::GRAPH_FAILED);
59+ OP_CHECK_IF(stdsList->GetSize() != MEANS_STDS_LEN,
60+ OP_LOGE(context, "stds length must be 4, but got %zu", stdsList->GetSize()), return ge::GRAPH_FAILED);
55 const float* means = meansList->GetData();61 const float* means = meansList->GetData();
56 const float* stds = stdsList->GetData();62 const float* stds = stdsList->GetData();
57 OP_CHECK_IF(means == nullptr || stds == nullptr, OP_LOGE(context, "means or stds data is null"),63 OP_CHECK_IF(means == nullptr || stds == nullptr, OP_LOGE(context, "means or stds data is null"),
@@ -70,6 +76,69 @@ static ge::graphStatus ParseMeansStds(gert::TilingContext* context, BoundingBoxE
70 return ge::GRAPH_SUCCESS;76 return ge::GRAPH_SUCCESS;
71}77}
72 78 
79+// Shape/dtype consistency checks that the geir path cannot enforce in InferShape:
80+// the built-in BoundingBoxEncode proto (libopsproto.so) registers a legacy V1 InferShape that
81+// shadows the custom IMPL_OP_INFERSHAPE, so these README constraints are validated here in tiling,
82+// which is the custom code path that actually executes.
83+// 1b: anchor_box.dtype == ground_truth_box.dtype
84+// 2a: shape[last] == 4
85+// 2b: anchor_box.shape == ground_truth_box.shape (exactly)
86+// 2c: rank == 2
87+static ge::graphStatus CheckInputsConsistency(gert::TilingContext* context)
88+{
89+ constexpr size_t RANK_2 = 2;
90+ constexpr size_t LAST_DIM_IDX = 1;
91+ constexpr int64_t BOX_COORD_NUM = 4;
92+ 
93+ auto anchorShapePtr = context->GetInputShape(0);
94+ OP_CHECK_NULL_WITH_CONTEXT(context, anchorShapePtr);
95+ auto gtShapePtr = context->GetInputShape(1);
96+ OP_CHECK_NULL_WITH_CONTEXT(context, gtShapePtr);
97+ const auto& anchorShape = anchorShapePtr->GetStorageShape();
98+ const auto& gtShape = gtShapePtr->GetStorageShape();
99+ 
100+ auto anchorDesc = context->GetInputDesc(0);
101+ OP_CHECK_NULL_WITH_CONTEXT(context, anchorDesc);
102+ auto gtDesc = context->GetInputDesc(1);
103+ OP_CHECK_NULL_WITH_CONTEXT(context, gtDesc);
104+ 
105+ // 1b: dtype consistency
106+ OP_CHECK_IF(anchorDesc->GetDataType() != gtDesc->GetDataType(),
107+ OP_LOGE(context, "anchor_box dtype (%d) and ground_truth_box dtype (%d) must be the same",
108+ static_cast<int>(anchorDesc->GetDataType()), static_cast<int>(gtDesc->GetDataType())),
109+ return ge::GRAPH_FAILED);
110+ 
111+ // 2c: rank == 2 (both inputs)
112+ OP_CHECK_IF(anchorShape.GetDimNum() != RANK_2,
113+ OP_LOGE(context, "anchor_box rank must be 2 (shape (N, 4)), but got rank %zu", anchorShape.GetDimNum()),
114+ return ge::GRAPH_FAILED);
115+ OP_CHECK_IF(
116+ gtShape.GetDimNum() != RANK_2,
117+ OP_LOGE(context, "ground_truth_box rank must be 2 (shape (N, 4)), but got rank %zu", gtShape.GetDimNum()),
118+ return ge::GRAPH_FAILED);
119+ 
120+ // 2a: last dim == 4 (both inputs)
121+ OP_CHECK_IF(
122+ anchorShape.GetDim(LAST_DIM_IDX) != BOX_COORD_NUM,
123+ OP_LOGE(context, "anchor_box last dim must be 4 (x1,y1,x2,y2), but got %ld", anchorShape.GetDim(LAST_DIM_IDX)),
124+ return ge::GRAPH_FAILED);
125+ OP_CHECK_IF(gtShape.GetDim(LAST_DIM_IDX) != BOX_COORD_NUM,
126+ OP_LOGE(context, "ground_truth_box last dim must be 4 (x1,y1,x2,y2), but got %ld",
127+ gtShape.GetDim(LAST_DIM_IDX)),
128+ return ge::GRAPH_FAILED);
129+ 
130+ // 2b: shape exactly equal (rank already both 2)
131+ for (size_t i = 0; i < RANK_2; ++i) {
132+ OP_CHECK_IF(anchorShape.GetDim(i) != gtShape.GetDim(i),
133+ OP_LOGE(context,
134+ "anchor_box and ground_truth_box shapes must be exactly the same, but dim[%zu] "
135+ "differs (%ld vs %ld)",
136+ i, anchorShape.GetDim(i), gtShape.GetDim(i)),
137+ return ge::GRAPH_FAILED);
138+ }
139+ return ge::GRAPH_SUCCESS;
140+}
141+ 
73static ge::graphStatus CalcUbSizing(gert::TilingContext* context, BoundingBoxEncodeTilingData* tiling, int64_t dim0,142static ge::graphStatus CalcUbSizing(gert::TilingContext* context, BoundingBoxEncodeTilingData* tiling, int64_t dim0,
74 ge::DataType dataType, uint64_t ubSize, int64_t coreNum, int64_t* outCoreNum)143 ge::DataType dataType, uint64_t ubSize, int64_t coreNum, int64_t* outCoreNum)
75{144{
@@ -148,6 +217,9 @@ static ge::graphStatus BoundingBoxEncodeTilingFunc(gert::TilingContext* context)
148 const std::set<ge::DataType> supportedDtype = {ge::DT_FLOAT16, ge::DT_FLOAT};217 const std::set<ge::DataType> supportedDtype = {ge::DT_FLOAT16, ge::DT_FLOAT};
149 OP_CHECK_IF(supportedDtype.count(dataType) == 0, OP_LOGE(context, "unsupported dtype"), return ge::GRAPH_FAILED);218 OP_CHECK_IF(supportedDtype.count(dataType) == 0, OP_LOGE(context, "unsupported dtype"), return ge::GRAPH_FAILED);
150 219 
220+ OP_CHECK_IF(CheckInputsConsistency(context) != ge::GRAPH_SUCCESS, OP_LOGE(context, "CheckInputsConsistency error"),
221+ return ge::GRAPH_FAILED);
222+ 
151 BoundingBoxEncodeTilingData* tiling = context->GetTilingData<BoundingBoxEncodeTilingData>();223 BoundingBoxEncodeTilingData* tiling = context->GetTilingData<BoundingBoxEncodeTilingData>();
152 OP_CHECK_NULL_WITH_CONTEXT(context, tiling);224 OP_CHECK_NULL_WITH_CONTEXT(context, tiling);
153 OP_CHECK_IF(memset_s(tiling, sizeof(BoundingBoxEncodeTilingData), 0, sizeof(BoundingBoxEncodeTilingData)) != EOK,225 OP_CHECK_IF(memset_s(tiling, sizeof(BoundingBoxEncodeTilingData), 0, sizeof(BoundingBoxEncodeTilingData)) != EOK,
@@ -13,20 +13,88 @@
13#include "register/op_impl_registry.h"13#include "register/op_impl_registry.h"
14#include "exe_graph/runtime/infer_shape_context.h"14#include "exe_graph/runtime/infer_shape_context.h"
15#include "op_common/log/log.h"15#include "op_common/log/log.h"
16+#include "op_common/op_host/util/shape_util.h"
16 17 
17using namespace ge;18using namespace ge;
18 19 
19namespace ops {20namespace ops {
20 21 
22+static constexpr int64_t IDX_ANCHOR = 0;
23+static constexpr int64_t IDX_GT = 1;
24+static constexpr int64_t IDX_OUT = 0;
25+static constexpr size_t RANK_2 = 2;
26+static constexpr size_t LAST_DIM_IDX = 1;
27+static constexpr int64_t BOX_COORD_NUM = 4;
28+ 
29+// Validate one box input's shape (rank==2, last dim==4) when the shape is statically known.
30+// Unknown-rank ([-2]) and unknown-dim (-1) cases are skipped to preserve dynamic-shape support.
31+static ge::graphStatus CheckBoxShape(gert::InferShapeContext* context, const gert::Shape& shape, const char* name)
32+{
33+ if (Ops::Base::IsUnknownRank(shape)) {
34+ return ge::GRAPH_SUCCESS;
35+ }
36+ if (shape.GetDimNum() != RANK_2) {
37+ OP_LOGE(context->GetNodeName(), "%s rank must be 2 (shape (N, 4)), but got rank %zu.", name, shape.GetDimNum());
38+ return ge::GRAPH_FAILED;
39+ }
40+ int64_t lastDim = shape.GetDim(LAST_DIM_IDX);
41+ if (lastDim != ge::UNKNOWN_DIM && lastDim != BOX_COORD_NUM) {
42+ OP_LOGE(context->GetNodeName(), "%s last dim must be 4 (x1,y1,x2,y2), but got %ld.", name, lastDim);
43+ return ge::GRAPH_FAILED;
44+ }
45+ return ge::GRAPH_SUCCESS;
46+}
47+ 
21static ge::graphStatus InferShape4BoundingBoxEncode(gert::InferShapeContext* context)48static ge::graphStatus InferShape4BoundingBoxEncode(gert::InferShapeContext* context)
22{49{
23- const gert::Shape* inputShape = context->GetInputShape(0);50+ const gert::Shape* anchorShape = context->GetInputShape(IDX_ANCHOR);
24- OP_CHECK_NULL_WITH_CONTEXT(context, inputShape);51+ OP_CHECK_NULL_WITH_CONTEXT(context, anchorShape);
52+ const gert::Shape* gtShape = context->GetInputShape(IDX_GT);
53+ OP_CHECK_NULL_WITH_CONTEXT(context, gtShape);
25 54 
26- gert::Shape* outputShape = context->GetOutputShape(0);55+ gert::Shape* outputShape = context->GetOutputShape(IDX_OUT);
27 OP_CHECK_NULL_WITH_CONTEXT(context, outputShape);56 OP_CHECK_NULL_WITH_CONTEXT(context, outputShape);
28 57 
29- *outputShape = *inputShape;58+ // 1b: dtype of anchor_box and ground_truth_box must be identical.
59+ const auto* anchorDesc = context->GetInputDesc(IDX_ANCHOR);
60+ OP_CHECK_NULL_WITH_CONTEXT(context, anchorDesc);
61+ const auto* gtDesc = context->GetInputDesc(IDX_GT);
62+ OP_CHECK_NULL_WITH_CONTEXT(context, gtDesc);
63+ if (anchorDesc->GetDataType() != gtDesc->GetDataType()) {
64+ OP_LOGE(context->GetNodeName(), "anchor_box dtype (%d) and ground_truth_box dtype (%d) must be the same.",
65+ static_cast<int>(anchorDesc->GetDataType()), static_cast<int>(gtDesc->GetDataType()));
66+ return ge::GRAPH_FAILED;
67+ }
68+ 
69+ // 2c rank==2 and 2a last-dim==4 for each box (guarded for dynamic shape).
70+ if (CheckBoxShape(context, *anchorShape, "anchor_box") != ge::GRAPH_SUCCESS) {
71+ return ge::GRAPH_FAILED;
72+ }
73+ if (CheckBoxShape(context, *gtShape, "ground_truth_box") != ge::GRAPH_SUCCESS) {
74+ return ge::GRAPH_FAILED;
75+ }
76+ 
77+ // 2b: anchor_box and ground_truth_box shapes must be exactly the same (compare known dims only).
78+ if (!Ops::Base::IsUnknownRank(*anchorShape) && !Ops::Base::IsUnknownRank(*gtShape)) {
79+ if (anchorShape->GetDimNum() != gtShape->GetDimNum()) {
80+ OP_LOGE(context->GetNodeName(), "anchor_box rank (%zu) and ground_truth_box rank (%zu) must be the same.",
81+ anchorShape->GetDimNum(), gtShape->GetDimNum());
82+ return ge::GRAPH_FAILED;
83+ }
84+ for (size_t i = 0; i < anchorShape->GetDimNum(); ++i) {
85+ int64_t aDim = anchorShape->GetDim(i);
86+ int64_t gDim = gtShape->GetDim(i);
87+ if (aDim != ge::UNKNOWN_DIM && gDim != ge::UNKNOWN_DIM && aDim != gDim) {
88+ OP_LOGE(context->GetNodeName(),
89+ "anchor_box and ground_truth_box shapes must be exactly the same, but dim[%zu] differs "
90+ "(%ld vs %ld).",
91+ i, aDim, gDim);
92+ return ge::GRAPH_FAILED;
93+ }
94+ }
95+ }
96+ 
97+ *outputShape = *anchorShape;
30 return ge::GRAPH_SUCCESS;98 return ge::GRAPH_SUCCESS;
31}99}
32 100