已关闭
[Bug-Report|缺陷反馈]: NMSWithMask InferShape 未校验 box_scores shape 契约并接受非法输入 #799
KaranocaVe创建于  8月24日关闭于  8月27日
KaranocaVe
KaranocaVe
8月24日 创建

一、问题描述

在 cann/ops-cv 的 commit
902202c68246f41b0efa06a3a3a849b426c5d372 中,
image/nms_with_mask/op_graph/nms_with_mask_proto.h 明确规定输入
box_scores 为二维 [N,5],并要求第二维等于 5。

但是 image/nms_with_mask/op_host/nms_with_mask_infershape.cpp 的
InferShape4NMSWithMask 只读取 GetDim(0)),没有检查输入 rank 或 GetDim(1))。因此 [16,4] 和 rank-1 [16] 都在 InferShape 阶段
返回成功,并被生成输出 [16,5]、[16]、[16]。同一版本的
Tiling 入口已经实现了对应的 rank/第二维检查并拒绝这些输入,说明
InferShape 与 Tiling 的输入契约不一致。

二、环境信息

  • 仓库/commit:cann/ops-cv /
    902202c68246f41b0efa06a3a3a849b426c5d372
  • 主机:Ubuntu 22.04.5、Linux 5.10、aarch64
  • Ascend 硬件:机器有 Ascend 910B3;本次为 Host InferShape/Tiling 验证
  • Driver/Toolkit/OPP:验证环境 CANN 9.1.0;源码为 9.2.0-beta.2 开发线
  • 编译器/Python/CMake:GCC/G++ 11.4.0、Python 3.12.13、CMake 3.22.1

三、重现步骤

  1. 将 ops-cv 固定到上述 commit,并按仓库 Host UT 配置构建
    nms_with_mask,目标 soc=ascend950;构建退出码为 0。
  2. 在已配置 CANN Toolkit 的环境运行上述 Host UT 用例。
  3. 对比以下输入的 InferShape 结果:
    • 合法对照:box_scores=[16,5]
    • 非法输入 A:box_scores=[16,4]
    • 非法输入 B:box_scores=[16]
  4. 使用同一 Host UT 上下文观察 Tiling 对非法输入的返回值,作为阶段间对照。

四、预期结果

合法 [16,5] 应返回 GRAPH_SUCCESS,并得到
[16,5]、[16]、[16] 输出。违反二维或第二维为 5 的约束时,
InferShape 应返回非 GRAPH_SUCCESS,不应继续生成合法形状的输出元数据。

五、实际结果

  • 合法 [16,5]:InferShape 返回 GRAPH_SUCCESS,输出为
    [16,5]、[16]、[16];Tiling 返回成功。
  • 非法 [16,4]:InferShape 返回 GRAPH_SUCCESS,输出仍为
    [16,5]、[16]、[16];Tiling 返回 GRAPH_FAILED。
  • 非法 [16]:InferShape 返回 GRAPH_SUCCESS,输出仍为
    [16,5]、[16]、[16];Tiling 返回 GRAPH_FAILED。
  • 两个非法 InferShape 用例重复 5 次结果一致。定向 Host UT 共 7/7 通过,
    运行退出码为 0。

关键源码位置:

  • image/nms_with_mask/op_graph/nms_with_mask_proto.h:27,44
  • image/nms_with_mask/op_host/nms_with_mask_infershape.cpp:27-43
  • image/nms_with_mask/op_host/arch35/nms_with_mask_tiling_arch35.cpp:47-59

六、影响与规避方式

图构建阶段可能接受不符合 NMSWithMask 输入协议的 Tensor,并传播与实际输入
不一致的输出 shape。后续阶段可能出现更晚的 shape/tiling 错误,调用方也会
收到误导性的 InferShape 成功结果。当前可行的规避方式是在调用 InferShape
前自行保证 box_scores 为二维且第二维为 5;实现侧应让 InferShape 与
Tiling 共享同一输入约束。

七、日志/最小复现

使用上述三组输入重复运行 InferShape 5 次,两个非法输入均稳定返回
GRAPH_SUCCESS,而同一输入在 Tiling 阶段返回 GRAPH_FAILED。首次测试框架配置
缺失导致的异常退出不属于本问题证据。

八、建议的回归测试

为 NMSWithMask InferShape 增加合法 [N,5]、非法 [N,4] 和
非法 rank-1 输入用例。合法用例应保持成功并生成三个正确输出 shape;两个
非法用例都应返回非 GRAPH_SUCCESS。同时保留现有 Tiling 负例,确保
InferShape 与 Tiling 对 rank 和第二维约束保持一致。

关联 PR

likedislike
KaranocaVeKaranocaVe
8月24日 添加了label:bug-report
KaranocaVeKaranocaVe
8月24日 关联了pull request:[Fix] 校验 NMSWithMask InferShape 的 box_scores shape
liu-wei
liu-wei成员
8月24日 评论:

已确认这是一个有效问题。

在 9.2.0-beta.2 分支的 commit 902202c68246f41b0efa06a3a3a849b426c5d372 上核对到,NMSWithMask 的 proto 对输入契约写得很明确:image/nms_with_mask/op_graph/nms_with_mask_proto.h:26-44 要求 box_scores 是二维 [N,5],且第二维必须等于 5。

Tiling 侧也已经实现了同等校验。image/nms_with_mask/op_host/arch35/nms_with_mask_tiling_arch35.cpp:41-60 中 CheckInputShape 会先检查输入是 2D,再检查 boxes 数量范围和第二维等于 5:

OP_CHECK_IF(shapeStorageScores.GetDimNum() != DIM_NUM_TWO,
            OP_LOGE(tilingContext_, "Input box_scores' shape only supports 2-D, got dim num:%lu.",
                    shapeStorageScores.GetDimNum()),
            return ge::GRAPH_FAILED);
...
OP_CHECK_IF(shapeStorageScores.GetDim(INDEX_ONE) != ELEMENT_NUM,
            OP_LOGE(tilingContext_, "Input box_scores' second dim must be 5, got :%lu.",
                    shapeStorageScores.GetDim(INDEX_ONE)),
            return ge::GRAPH_FAILED);

但 InferShape 侧没有对应检查。image/nms_with_mask/op_host/nms_with_mask_infershape.cpp:27-43 只读取输入第 0 维,然后固定生成三个输出 shape:

const gert::Shape* input_scores_shape = context->GetInputShape(0);
OP_CHECK_NULL_WITH_CONTEXT(context, input_scores_shape);
...
output_shape->SetDim(0, input_scores_shape->GetDim(0));
...
output_shape->SetDim(1, OUTPUT_DIM_VALUE);

这里没有检查 input_scores_shape->GetDimNum()==2,也没有检查 GetDim(1)==5。因此 [16,4] 或 rank-1 [16] 这类违反 proto 约束的输入,会在 InferShape 阶段被静默推导为 [16,5]、[16]、[16],而同一输入在 Tiling 阶段会失败,形成 Host 阶段契约不一致。

当前 InferShape UT image/nms_with_mask/tests/ut/op_host/test_nms_with_mask_infershape.cpp:28-38 只覆盖了 {-2,5} 的成功推导,没有覆盖 [N,4]、rank-1、rank-3 等非法输入。Tiling UT image/nms_with_mask/tests/ut/op_host/test_nms_with_mask_tiling.cpp:40-65 也只看到合法 [16,5] 成功路径。

建议按缺陷处理:在 InferShape4NMSWithMask 中补齐与 Tiling 一致的输入 shape 校验,包括 rank 为 2、第二维为 5、N 的合法范围;并新增 [16,5] 成功、[16,4] 失败、[16] 失败、rank-3 失败等回归用例,确保 InferShape 与 Tiling 对输入契约保持一致。

likedislike
Ssunhao_hw成员
8月24日 将 sunhao_hw 设为负责人
sunhao_hw成员
8月25日 评论:

您好,对应PR麻烦在编译前先本地解决precommit问题后重新提交编译。
precommit可以参考如下配置:precommit配置指南

likedislike
Ssunhao_hw成员
8月25日 添加了label:wait-feedback
CANN-robotCANN-robot成员
8月27日 关闭了 issue
CANN-robotCANN-robot成员
8月27日 添加了label:resolved
KaranocaVeKaranocaVe
13 天前 修改了issue 的描述