已关闭
[Bug] strided_slice_assign_v2 负 axes 导致 host abort(AdjustWithAxes 未校验) #2485
Agent-Bug-Hunter创建于  28 天前关闭于  13 天前
Agent-Bug-Hunter
28 天前 创建

摘要

aclnnStridedSliceAssignV2 的 host tiling AdjustWithAxesaxes[i] 直接用作 beginAdjust / endAdjust / stridesAdjust 下标,未校验 0 ≤ axes[i] < dimNum


环境

芯片 Ascend910B3
CANN 9.1.0-beta.3
ops-math HEAD 2d1098d3e902
编译命令 见下文「完整复现过程」
安装方式 cann-ops-math-cann_scan_repro_linux-*.run$ASCEND_HOME_PATH/vendors/cann_scan_repro_math
Track / Pattern A / P-011
Finding MATH-SSAV2-001
运行时证明 见下文「为何确认跑的是源码编译内核」

为什么认为这是问题:期望 vs 实际

输入(与复现用例一致)

var/input 合法 shape;axes 含负数(如 axes={-1,1}),触发 AdjustWithAxes 路径

期望行为

用例 期望
axes 含合法负轴(归一化到正轴)或非法轴 拒绝非法 / 或按文档规范化后成功
负 axes 不得导致 host 崩溃 返回参数错误,进程不 abort

实际行为(aclnn / 源码编译安装路径)

用例 API 返回 关键输出 说明
axes={-1,1} 进程 free(): invalid pointer 后 exit 42 host abort,属防御性缺陷

对比结论

期望 实际
负 axes 拒绝或安全规范化 host heap abort
接口契约 参数错误码 未校验导致崩溃

根因

Positive OOB axes ({99} / {2}) are rejected with 561002 (API layer). Negative axes are not rejected and reach host tiling AdjustWithAxes, which indexes beginAdjust[axes[i]] with no axes ∈ [0, dimNum) check.

(详细行号见同目录 FINDING.md 与算子源码;归档时已通过 aclnn exit 42 确认。)


为何确认跑的是源码编译内核(非 built-in)

  1. 环境:安装自定义包后执行 source $ASCEND_HOME_PATH/vendors/cann_scan_repro_math/bin/set_env.bashASCEND_CUSTOM_OPP_PATH 指向该 vendor。
  2. 二进制路径:复现链接/加载 vendor 下 op_api / op_impl,而非仅依赖 CANN built-in 同名算子(见 repro_manifest.jsonbuilt_from_source=true)。
  3. (推荐)排除 built-in:临时移走 built-in 对应算子内核目录后仍能 exit 42。

完整复现过程

占位符:$ASCEND_HOME_PATH / $OPS_MATH / $REPRO_ROOT

步骤 1:环境使能

source <CANN安装目录>/ascend-toolkit/set_env.sh

步骤 2:源码编译单算子包

cd "$OPS_MATH"
bash build.sh --pkg --soc=ascend910b --ops=strided_slice_assign_v2 \
  --vendor_name=cann_scan_repro -j8

成功标志:生成 $OPS_MATH/build_out/cann-ops-math-cann_scan_repro_linux-*.run

步骤 3:安装并切换到自定义包

bash $OPS_MATH/build_out/cann-ops-math-cann_scan_repro_linux-*.run \
  --quiet --install-path="$ASCEND_HOME_PATH"
source "$ASCEND_HOME_PATH/vendors/cann_scan_repro_math/bin/set_env.bash"
echo "ASCEND_CUSTOM_OPP_PATH=$ASCEND_CUSTOM_OPP_PATH"

步骤 4:放置复现源码与执行脚本

$REPRO_ROOT/
  test_aclnn_ssav2_negaxes.cpp
  build_and_run_repro.sh

(本 draft 目录内已含上述文件,可直接作为 $REPRO_ROOT。)

步骤 5:编译并运行

cd "$REPRO_ROOT"
chmod +x build_and_run_repro.sh
bash build_and_run_repro.sh --vendor cann_scan_repro --src test_aclnn_ssav2_negaxes.cpp
# 退出码 42 = BUG_REPRODUCED

成功复现标志:进程退出码 42

实际运行摘录

[env] sourced $ASCEND_HOME_PATH/vendors/cann_scan_repro_math/bin/set_env.bash
[env] ASCEND_CUSTOM_OPP_PATH=$ASCEND_HOME_PATH/vendors/vendors/cann_scan_repro_math:
[build] g++ $REPRO_ROOT/test_aclnn_ssav2_negaxes.cpp
[run] $REPRO_ROOT/test_aclnn_ssav2_negaxes
free(): invalid pointer
[exit] 42  (42=BUG_REPRODUCED, 0=NO_REPRO, 1=harness error)

复现用例源码

文件名:test_aclnn_ssav2_negaxes.cpp

#include <cstdio>
#include <csignal>
#include <cstdlib>
#include <vector>
#include "acl/acl.h"
#include "aclnnop/aclnn_strided_slice_assign_v2.h"
#define LOG_PRINT(m,...) do{printf(m,##__VA_ARGS__);}while(0)
static void OnCrash(int sig){LOG_PRINT("BUG_REPRODUCED: host crash sig=%d case=negaxes\n",sig);_Exit(42);}
static int64_t GS(const std::vector<int64_t>& s){int64_t n=1;for(auto i:s)n*=i;return n;}
template<typename T>
static int CT(const std::vector<T>& h,const std::vector<int64_t>& shape,void** d,aclDataType dt,aclTensor** t){
  auto size=GS(shape)*sizeof(T);
  aclrtMalloc(d,size,ACL_MEM_MALLOC_HUGE_FIRST);
  aclrtMemcpy(*d,size,h.data(),size,ACL_MEMCPY_HOST_TO_DEVICE);
  std::vector<int64_t> st(shape.size(),1);
  for(int64_t i=(int64_t)shape.size()-2;i>=0;i--) st[i]=shape[i+1]*st[i+1];
  *t=aclCreateTensor(shape.data(),shape.size(),dt,st.data(),0,ACL_FORMAT_ND,shape.data(),shape.size(),*d);
  return 0;
}
int main(){
  std::signal(SIGSEGV,OnCrash); std::signal(SIGABRT,OnCrash); std::signal(SIGBUS,OnCrash);
  aclrtStream stream; aclInit(nullptr); aclrtSetDevice(0); aclrtCreateStream(&stream);
  std::vector<int64_t> varShape={4,3}, valShape={2,2};
  void *varDev=nullptr,*valDev=nullptr; aclTensor *varRef=nullptr,*inputValue=nullptr;
  std::vector<float> varHost={0,1,2,3,4,5,6,7,8,9,10,11}, valHost={-1,-2,-3,-4};
  std::vector<int64_t> beginData={1,0}, endData={4,2}, stridesData={2,1}, axesData={-1,1};
  CT(varHost,varShape,&varDev,ACL_FLOAT,&varRef);
  CT(valHost,valShape,&valDev,ACL_FLOAT,&inputValue);
  auto begin=aclCreateIntArray(beginData.data(),beginData.size());
  auto end=aclCreateIntArray(endData.data(),endData.size());
  auto strides=aclCreateIntArray(stridesData.data(),stridesData.size());
  auto axes=aclCreateIntArray(axesData.data(),axesData.size());
  uint64_t ws=0; aclOpExecutor* ex=nullptr;
  auto ret=aclnnStridedSliceAssignV2GetWorkspaceSize(varRef,inputValue,begin,end,strides,axes,&ws,&ex);
  LOG_PRINT("GetWS ret=%d ws=%llu\n", ret, (unsigned long long)ws);
  if(ret==0){
    void* wa=nullptr; if(ws) aclrtMalloc(&wa,ws,ACL_MEM_MALLOC_HUGE_FIRST);
    auto r2=aclnnStridedSliceAssignV2(wa,ws,ex,stream);
    auto r3=aclrtSynchronizeStream(stream);
    LOG_PRINT("launch=%d sync=%d\n",r2,r3);
    if(r2==0&&r3==0){LOG_PRINT("BUG_REPRODUCED: illegal input accepted\n"); return 42;}
  }
  LOG_PRINT("NO_REPRO\n"); return 0;
}

执行脚本

文件名:build_and_run_repro.sh

#!/usr/bin/env bash
set -euo pipefail
VENDOR=""; SRC_NAME=""
while [[ $# -gt 0 ]]; do
  case "$1" in
    --vendor) VENDOR="$2"; shift 2 ;;
    --src) SRC_NAME="$2"; shift 2 ;;
    *) echo "unknown arg: $1" >&2; exit 2 ;;
  esac
done
: "${ASCEND_HOME_PATH:?}"
ROOT="$(cd "$(dirname "$0")" && pwd)"
if [[ -z "$SRC_NAME" ]]; then
  mapfile -t _srcs < <(ls "$ROOT"/test_aclnn_*.cpp 2>/dev/null || true)
  [[ ${#_srcs[@]} -eq 1 ]] || { echo "need --src"; exit 2; }
  SRC="${_srcs[0]}"
else SRC="$ROOT/$SRC_NAME"; fi
BIN="${SRC%.cpp}"
if [[ -n "$VENDOR" ]]; then
  for cand in "${ASCEND_HOME_PATH}/vendors/${VENDOR}_math" "${ASCEND_HOME_PATH}/vendors/${VENDOR}"; do
    if [[ -f "$cand/bin/set_env.bash" ]]; then
      set +u; source "$cand/bin/set_env.bash"; set -u
      echo "[env] sourced $cand/bin/set_env.bash"
      echo "[env] ASCEND_CUSTOM_OPP_PATH=${ASCEND_CUSTOM_OPP_PATH:-}"
      break
    fi
  done
fi
INC="${ASCEND_HOME_PATH}/aarch64-linux/include"; LIB="${ASCEND_HOME_PATH}/aarch64-linux/lib64"
echo "[build] g++ $SRC"
g++ -std=c++17 -O2 "$SRC" -I"$INC" -I"$INC/aclnnop" -L"$LIB" -Wl,-rpath,"$LIB" \
  -lascendcl -lnnopbase -lopapi -o "$BIN"
echo "[run] $BIN"
set +e; "$BIN"; RC=$?; set -e
echo "[exit] $RC  (42=BUG_REPRODUCED, 0=NO_REPRO, 1=harness error)"
exit "$RC"

修复建议

在 host/tiling/kernel 入口拒绝非法索引或控制量,返回明确参数错误;勿静默 OOB。


人工复核说明

Agent 复现结果供参考;语义边界(是否允许 wrap、文档是否声明调用方契约)以人工结论与产品规范为准。

likedislike
陈思陈思成员
27 天前 关联了pull request:fix(conversion): validate pad and slice axes bounds
陈思
陈思成员
27 天前 评论:

收到,已联系算子责任人确认修复中

likedislike
陈思陈思成员
27 天前 删除了关联的pull request:fix(conversion): validate pad and slice axes bounds
陈思
陈思成员
27 天前 评论:

/assign @chensi79

likedislike
CANN-robotCANN-robot成员
27 天前 将 chensi79 设为负责人
陈思陈思成员
26 天前 移除了负责人 chensi79
陈思陈思成员
26 天前 将 sunchun 设为负责人
Xu-XuePengXu-XuePeng成员
18 天前 关联了pull request:fix: StridedSliceAssignV2 负 axes 归一化与越界校验
陈思陈思成员
14 天前 issue状态由 进行中 改变为 挂起
CANN-robotCANN-robot成员
13 天前 关闭了 issue
CANN-robotCANN-robot成员
13 天前 添加了label:resolved