问题:aclnnAdaLayerNormBackward 在可选输出为 nullptr 时 SIGSEGV
原A2/A3引入 非A5长尾算子支持代码引入问题 与issue173问题重复
根因

op_api 未对可选输出做空指针判断,对 nullptr 的 aclTensor 调用了 GetDataType()。
- 文件:norm/ada_layer_norm_grad/op_host/op_api/aclnn_ada_layer_norm_backward.cpp
- GenOutWithMask()(L352-363):
if (mask) {
CHECK_RET(tempOut != nullptr, ACLNN_ERR_INNER_NULLPTR);
auto tempCast = l0op::Cast(tempOut, output->GetDataType(), executor); // output 为 nullptr 时崩溃 - L455-457 对 gradInputOut/gradScaleOut/gradShiftOut 硬编码 mask=true(而 L458-459 对 gradWeightOut/gradBiasOut 用了 != nullptr),导致这三个输出任一为空即空指针解引用。


📎 复现附件下载(aclnnAdaLayerNormBackward gradInputOut nullptr 进程core 场景:执行步骤说明 + 压测 CPP + plog + 执行日志 + 分析报告):
aclnnAdaLayerNormBackward_error.zip
附件已存放在 Alice_zhou/issue 仓,点击上方链接直接下载(原结果服务器附件链接因服务器网络故障不可用,已改用本仓托管)。


DTS2026102323776


复测验证 OK(2026-11-04,CANN 9.3.0):error 场景 1000 条压测无 SIGSEGV,gradInputOut=nullptr 时 GetWorkspaceSize 段错误已消除。


回归验证通过(2026-11-14,CANN 9.3.0,issue 回归测试)
按 issue 附件最小复现 CPP(base 构造满足 md 全部约束、仅注入单参数 nullptr)验证修复效果:
| 验证场景 | 原现象 | 现结果 |
|---|---|---|
| gradInputOut=nullptr(本 issue 场景) | GWS 段错误 SIGSEGV(退出码 139,崩溃于 aclTensor::GetDataType() 空指针解引用) | 无崩溃(退出码 0),GWS ret=0 正常返回 ✅ |
| gradScaleOut=nullptr(责任方根因中同款 GenOutWithMask 硬编码 mask=true 的输出) | 同类崩溃风险 | 无崩溃,GWS ret=0 ✅ |
| gradShiftOut=nullptr(同上) | 同类崩溃风险 | 无崩溃,GWS ret=0 ✅ |
结论:GenOutWithMask()(aclnn_ada_layer_norm_backward.cpp L352-363)对 gradInputOut/gradScaleOut/gradShiftOut 的空指针崩溃已消除,修复生效,回归验证通过。
遗留观察(非阻塞):三个必需输出 nullptr 时 GWS 现返回 ret=0(执行成功)而非 md 错误码表规定的 161001(ACLNN_ERR_PARAM_NULLPTR)——崩溃已修复,但参数空指针校验缺失与 md 错误码描述仍不一致(与 changwei#204 中可选输出 gradWeightOut/gradBiasOut nullptr 合法不同,这三个为必需输出)。可另行确认是否需要补充 161001 校验,不影响本 issue 关闭。


一、问题描述(必填)
aclnnAdaLayerNormBackward;异常场景:gradInputOut=nullptr(NULLPTR_OUTPUT)aclnnAdaLayerNormBackwardGetWorkspaceSize在 gradInputOut(必需输出 tensor)传入 nullptr 时发生段错误(SIGSEGV,进程崩溃退出码 139),崩溃点为aclTensor::GetDataType()空指针解引用(libopapi_nn.so)二、问题复现步骤(必填)
aclnnAdaLayerNormBackward_error.cpp放入对应目录下):rm -rf aclnnAPI_fuzz/src/op/* # 将附件 cpp(单场景 gradInputOut=nullptr 最小复现)保存为 aclnnAPI_fuzz/src/op/aclnnAdaLayerNormBackward_error.cppcd aclnnAPI_fuzz/ ; makecd out ; ./aclnnAPI_fuzz aclnnAdaLayerNormBackward_error_fuzz复现基线构造(满足 md 全部约束):input/gradOut/gradInputOut=[2,4,16],mean/rstd=[2,4,1],scale/shift/gradScaleOut/gradShiftOut=[2,16],weight/bias/gradWeight/gradBias=[16],normalizedShape=[16],全部 FLOAT,仅
gradInputOut置 nullptr。三、附件与证据(必填)
单场景最小复现 CPP(gradInputOut=nullptr,可直接编译执行):
#include <iostream> #include <vector> #include <cstring> #include <unistd.h> #include "acl/acl.h" #include "aclnn/aclnn_base.h" #include "acl/acl_base.h" #include "acl/acl_rt.h" #include "sec_common.h" #include "utils.h" #include "aclnnop/aclnn_ada_layer_norm_backward.h" using namespace std; // 单场景最小复现:gradInputOut = nullptr 时 aclnnAdaLayerNormBackwardGetWorkspaceSize 段错误 // base 构造完全满足 md 约束:input/gradOut/gradInputOut=[2,4,16],mean/rstd=[2,4,1], // scale/shift/gradScaleOut/gradShiftOut=[2,16],weight/bias/gradWeight/gradBias=[16],normalizedShape=[16],全 FLOAT int RunRepro() { auto ret = Init(deviceId, &context, &stream); if (ret != ACL_SUCCESS) { printf("Init failed %d\n", (int)ret); return 1; } setvbuf(stdout, NULL, _IONBF, 0); printf("[REPRO] aclnnAdaLayerNormBackward gradInputOut=nullptr 单场景复现开始\n"); std::vector<int64_t> inputShape = {2, 4, 16}; std::vector<int64_t> meanShape = {2, 4, 1}; std::vector<int64_t> scaleShape = {2, 16}; std::vector<int64_t> weightShape = {16}; std::vector<int64_t> normArr = {16}; void* goA=nullptr; aclTensor* go=nullptr; void* inA=nullptr; aclTensor* in=nullptr; void* meA=nullptr; aclTensor* me=nullptr; void* rsA=nullptr; aclTensor* rs=nullptr; void* scA=nullptr; aclTensor* sc=nullptr; void* shA=nullptr; aclTensor* sh=nullptr; void* wtA=nullptr; aclTensor* wt=nullptr; void* biA=nullptr; aclTensor* bi=nullptr; void* giA=nullptr; aclTensor* gi=nullptr; void* gsA=nullptr; aclTensor* gs=nullptr; void* ghA=nullptr; aclTensor* gh=nullptr; void* gwA=nullptr; aclTensor* gw=nullptr; void* gbA=nullptr; aclTensor* gb=nullptr; uint64_t ws=0; aclOpExecutor* ex=nullptr; void* wsAddr=nullptr; aclIntArray* ns=nullptr; int rc = 0; { std::vector<float> xh(128, 1.5f), mh(8, 0.5f), ph(32, 1.0f), oh(128, 0.0f), wh(16, 1.0f); CreateAclTensor_New(xh, inputShape, &goA, ACL_FLOAT, ACL_FORMAT_ND, &go); CreateAclTensor_New(xh, inputShape, &inA, ACL_FLOAT, ACL_FORMAT_ND, &in); CreateAclTensor_New(mh, meanShape, &meA, ACL_FLOAT, ACL_FORMAT_ND, &me); CreateAclTensor_New(mh, meanShape, &rsA, ACL_FLOAT, ACL_FORMAT_ND, &rs); CreateAclTensor_New(ph, scaleShape, &scA, ACL_FLOAT, ACL_FORMAT_ND, &sc); CreateAclTensor_New(ph, scaleShape, &shA, ACL_FLOAT, ACL_FORMAT_ND, &sh); CreateAclTensor_New(wh, weightShape, &wtA, ACL_FLOAT, ACL_FORMAT_ND, &wt); CreateAclTensor_New(wh, weightShape, &biA, ACL_FLOAT, ACL_FORMAT_ND, &bi); CreateAclTensor_New(oh, inputShape, &giA, ACL_FLOAT, ACL_FORMAT_ND, &gi); CreateAclTensor_New(ph, scaleShape, &gsA, ACL_FLOAT, ACL_FORMAT_ND, &gs); CreateAclTensor_New(ph, scaleShape, &ghA, ACL_FLOAT, ACL_FORMAT_ND, &gh); CreateAclTensor_New(wh, weightShape, &gwA, ACL_FLOAT, ACL_FORMAT_ND, &gw); CreateAclTensor_New(wh, weightShape, &gbA, ACL_FLOAT, ACL_FORMAT_ND, &gb); ns = aclCreateIntArray(normArr.data(), normArr.size()); // ===== 注入唯一异常点:gradInputOut = nullptr ===== aclDestroyTensor(gi); gi = nullptr; printf("[FUZZ_ERROR_POINT] case_0: errorType=NULLPTR_OUTPUT, errorTarget=gradInputOut, description=gradInputOut tensor is nullptr (md错误码表规定应返回161001)\n"); printf("[FUZZ_PARAM] gradOut: dtype=FLOAT, shape=[2,4,16]; input: dtype=FLOAT, shape=[2,4,16]; normalizedShape=[16]; mean/rstd: shape=[2,4,1]; scale/shift: shape=[2,16]; weight/bias: shape=[16]; gradInputOut=nullptr\n"); printf("[FUZZ_LOG] plog_file: aclnnAdaLayerNormBackward_error_plog_case_0.log\n"); ret = aclnnAdaLayerNormBackwardGetWorkspaceSize(go, in, ns, rs, me, sc, sh, wt, bi, gi, gs, gh, gw, gb, &ws, &ex); printf("[REPRO] GetWorkspaceSize ret=%d (期望 161001, 实际发生 SIGSEGV 则为 bug)\n", (int)ret); printf("aclnnAdaLayerNormBackward execute failed :%d\n", (int)ret); rc = (int)ret; if (ret == ACL_SUCCESS) { if (ws > 0) { aclrtMalloc(&wsAddr, ws, ACL_MEM_MALLOC_HUGE_FIRST); } ret = aclnnAdaLayerNormBackward(wsAddr, ws, ex, stream); printf("aclnnAdaLayerNormBackward execute success :%d\n", (int)ret); rc = 0; aclrtSynchronizeStream(stream); } printf("[FUZZ_RESULT] case_0: %s, ret=%d\n", (rc == 0) ? "success" : "faild", rc); } if (go) aclDestroyTensor(go); if (in) aclDestroyTensor(in); if (me) aclDestroyTensor(me); if (rs) aclDestroyTensor(rs); if (sc) aclDestroyTensor(sc); if (sh) aclDestroyTensor(sh); if (wt) aclDestroyTensor(wt); if (bi) aclDestroyTensor(bi); if (gi) aclDestroyTensor(gi); if (gs) aclDestroyTensor(gs); if (gh) aclDestroyTensor(gh); if (gw) aclDestroyTensor(gw); if (gb) aclDestroyTensor(gb); if (ns) aclDestroyIntArray(ns); if (goA) aclrtFree(goA); if (inA) aclrtFree(inA); if (meA) aclrtFree(meA); if (rsA) aclrtFree(rsA); if (scA) aclrtFree(scA); if (shA) aclrtFree(shA); if (wtA) aclrtFree(wtA); if (biA) aclrtFree(biA); if (giA) aclrtFree(giA); if (gsA) aclrtFree(gsA); if (ghA) aclrtFree(ghA); if (gwA) aclrtFree(gwA); if (gbA) aclrtFree(gbA); if (ws > 0 && wsAddr) aclrtFree(wsAddr); aclrtDestroyStream(stream); aclrtDestroyContext(context); aclrtResetDevice(deviceId); aclFinalize(); return rc; } extern "C" int aclnnAdaLayerNormBackward_error_fuzz(int argc, char *argv[]); int aclnnAdaLayerNormBackward_error_fuzz(int argc, char *argv[]) { return RunRepro(); }💡 该问题由 fuzz 自动化压测平台发现;同接口其余 nullptr 参数(gradInputOut/gradScaleOut/gradShiftOut)分别独立提单,一个场景一个 issue。