已关闭
[Bug-Report|缺陷反馈]: aclnnApplyTopKTopP 的 p/k 双空校验仅记日志未返回,非法入参被放行并产生静默错误结果 #5999
liuhanwen8创建于  25 天前关闭于  15 天前
liuhanwen8
liuhanwen8
25 天前 创建

问题描述

aclnnApplyTopKTopP 第一段接口中,对「p 与 k 同时为空」这一非法组合的校验只打印日志、未返回失败,导致该非法入参被判定为合法并继续执行,最终产生静默错误结果或语义失真的内部错误码。

算子契约(README.md 约束说明)与接口资料均明确要求:p 和 k 为可选输入,二者不能同时为空,至少传入一个。代码中的错误文本也逐字复述了这条约束,但控制流没有落实。

问题代码位置

index/apply_top_k_top_p_with_sorted/op_api/aclnn_apply_top_k_top_p.cpp:47-55

static bool CheckNotNull(const aclTensor* logits, const aclTensor* p, const aclTensor* k, const aclTensor* out)
{
    OP_CHECK_NULL(logits, return false);
    if (p == nullptr && k == nullptr) {
        OP_LOGE(ACLNN_ERR_PARAM_INVALID, "The inputs, p and k, should not be nullptr at the same time.");
    }
    OP_CHECK_NULL(out, return false);
    return true;
}

第 50-52 行检测到「双空」后仅记录日志,缺少 return false;,函数继续执行到第 54 行 return true;。

一、调用链推演:非法组合被判定为合法

CheckParams()(同文件 :121-137)按顺序调用四个校验,双空时逐个「顺利通过」:

步骤 函数 双空(p==nullptr && k==nullptr)时的行为 结果
1 CheckNotNull (:47-55) L50 命中 → L51 仅 OP_LOGE → 落到 L54 return true 通过(缺陷点)
2 CheckDtypeValid (:57-75) L61 if (p != nullptr)、L64 if (k != nullptr) 均跳过 通过
3 CheckShapeValid (:77-98) L81 if (p != nullptr)、L84 if (k != nullptr) 均跳过 通过
4 CheckFormatValid (:100-119) L106 if (p != nullptr)、L110 if (k != nullptr) 均跳过 通过

即 CheckParams() 于 L136 return ACLNN_SUCCESS;。后续 :152-165 的 pIsEmpty / kIsEmpty 因 p、k 皆为 nullptr 而保持 false,L160 的空 tensor 短路分支也不会命中,非法入参被完整放行至下游。

二、非对称性证据:同文件同函数族唯一被漏掉的 return

统计同文件 OP_LOGE 与其下一行语句的配对关系,可以清楚看到漏改的孤立性:

行号 所在函数 OP_LOGE 之后的语句 是否返回
:103 CheckFormatValid return false; ✅
:107 CheckFormatValid return false; ✅
:111 CheckFormatValid return false; ✅
:115 CheckFormatValid return false; ✅
:88(返回在 :90) CheckShapeValid return false; ✅
:93(返回在 :95) CheckShapeValid return false; ✅
:51 CheckNotNull }(直接落入 return true) ❌ 缺失

全文件 7 处 OP_LOGE 中,唯独第 51 行之后没有返回语句。同文件其余 6 处校验均采用「记日志 + 返回失败」的一致写法(该文件 return false 共 18 处、CHECK_RET 共 13 处),属单点遗漏而非有意设计。

三、错误码与资料契约不符

接口资料 docs/aclnnApplyTopKTopP.md:195-203 的第一段接口报错表明确划分了两种返回码:

返回码 错误码 描述(资料原文)
ACLNN_ERR_PARAM_NULLPTR 161001 传入的logits、out是空指针或p与k同为空指针
ACLNN_ERR_PARAM_INVALID 161002 logits、p、k或out的数据类型不在支持的范围之内 / 数据类型不匹配 / shape不匹配

按资料,「p 与 k 同为空指针」应返回 161001。但代码第 51 行:

  1. 把 ACLNN_ERR_PARAM_INVALID(对应 161002)作为 OP_LOGE 的首个参数传入 —— 与资料规定的 161001 类别不符;
  2. 由于没有 return false,这个错误码只出现在日志文本里,不会作为返回码对外返回。

四、实际后果(两条下游路径,均为错误行为)

放行后 logits 的尾维大小决定走向哪条路径:

路径 A —— logits 尾维为 1(命中 :181-182)

179:     bool isLastDimSizeOne = logits->GetViewShape()[DIM_ONE] == 1;
180:     auto viewCopyResult = logitsContiguous;
181:     if (isLastDimSizeOne) {
182:         viewCopyResult = l0op::ViewCopy(logitsContiguous, out, uniqueExecutor.get());

该分支只做一次直拷,既不执行 top-k 也不执行 top-p,随后于 :197-199 正常返回 ACLNN_SUCCESS。即:

  • 返回码为 0(成功);
  • out 被静默写为 logits 原值,未做任何过滤。

这是静默错误结果:调用方拿到「成功」与全量未过滤的 logits,无任何异常提示。同时该行为也与算子资料给出的计算公式(probsValue = softmax(...)、probsSum = cumsum(...)、topPMask 过滤)完全不符——out 本应是过滤后的结果。

路径 B —— logits 尾维大于 1(命中 :189-191)

189:         auto res = l0op::ApplyTopKTopPWithSorted(sortedValue, sortedIndices, pContiguous, kContiguous, logitsContiguous,
190:                                                  uniqueExecutor.get());
191:         CHECK_RET(res != nullptr, ACLNN_ERR_INNER_NULLPTR);

此时 pContiguous / kContiguous 均为 nullptr(:169-178 因 p == nullptr、k == nullptr 未赋值),被直接传入 l0op。若 l0op 因双空返回 nullptr,接口将返回 ACLNN_ERR_INNER_NULLPTR —— 属内部错误码,用户无从判断是「入参组合非法」,排障语义失真。

likedislike
liuhanwen8liuhanwen8
25 天前 添加了label:bug-report
yuning_chen
yuning_chen成员
24 天前 评论:

初步分析

感谢反馈,我们已开始核对这个问题。

现象理解:期望 p 与 k 同时为空时,第一段接口拦截并返回空指针类错误码;正文称 CheckNotNull 仅打日志后仍返回成功,非法组合被放行,可能静默写出未过滤结果或变成内部错误码。
当前判断:初步判断,待复现确认。从给出的代码看,双空分支缺少失败返回的可能性存在,但实际返回码和 out 内容需按「二者均为空指针」实测,不能当作已确认根因。
涉及范围:aclnnApplyTopKTopP 的空指针校验(aclnn_apply_top_k_top_p.cpp)。
下一步:我们会按该组合补充核对与复现,确认是否需补失败返回、对齐资料错误码,以及是否漏测。

likedislike
yuning_chenyuning_chen成员
24 天前 将 bartonfang 设为负责人
yuning_chen
yuning_chen成员
24 天前 评论:

您好,问题已收到,目前 @bartonfang 正在处理中。

likedislike
yangziqi007
yangziqi007
22 天前 评论:

/assign

likedislike
CANN-robotCANN-robot成员
22 天前 将 yangziqi_007 设为负责人
liuhanwen8liuhanwen8
22 天前 修改了issue 的描述
yangziqi007yangziqi007
19 天前 关联了pull request:fix(apply_top_k_top_p): 拦截 p 和 k 同时为空
CANN-robotCANN-robot成员
15 天前 关闭了 issue
yangziqi007
yangziqi007
15 天前 评论:

感谢指出,问题已修复合入

likedislike
CANN-robotCANN-robot成员
15 天前 添加了label:resolved