已关闭
【缺陷报告】数据类型截断 - 文件concat.h - 函数GenMaskReg - 行号256 #260
zhangjunkai9创建于  8月20日关闭于  14 天前
zhangjunkai9
8月20日 创建

缺陷信息

缺陷类型dataTypeTruncation (数据类型截断)
函数GenMaskReg
文件autofuse/v35/ascendc/api_regbase/concat.h
行号256
置信度85%

缺陷描述

函数 GenMaskReg 在第 256 行计算 tail_mask = (1U << (tail_num * sizeof(U))) - 1U,其中 1U 为 unsigned int(32 位),移位结果为 32 位无符号整数。但 tail_mask 声明为 uint16_t(16 位),赋值时高位被截断。U 的类型由 ConcatExtend 第 363 行决定:using U = std::conditional_t<sizeof(T) == sizeof(uint32_t), uint32_t, uint16_t>。当 U = uint16_t(sizeof=2)时,tail_num = gather_mask_dim_size % 16,取值 0-15,tail_num * 2 取值 0-30,当 tail_num > 8 时掩码需要超过 16 位;当 U = uint32_t(sizeof=4)时,tail_num = gather_mask_dim_size % 8,取值 0-7,tail_num * 4 取值 0-28,当 tail_num > 4 时掩码需要超过 16 位。截断后的 tail_mask 被存入 index_addr[i](uint32_t *),高 16 位始终为 0,导致 Gather 操作使用错误的掩码,可能读取/写入错误数据。调用链验证:ConcatExtendDyn:548 → ConcatExtend:389 → ScatterInputPadded:307 → GenMaskReg:248,从入口可达。

事实核查

核查1(模式成立):第256行 const uint16_t tail_mask = (1U << (tail_num * sizeof(U))) - 1U,1U 为 32 位无符号整数,移位结果为 32 位,赋值给 uint16_t 时高位截断。
U=uint16_t(sizeof=2)时 tail_num=gather_mask_dim_size%16 取值0-15,tail_num*2 取值0-30,tail_num>8 时掩码需超过16位被截断;U=uint32_t(sizeof=4)时 tail_num=gather_mask_dim_size%8 取值0-7,tail_num*4 取值0-28,tail_num>4 时截断。
截断后 tail_mask 存入 index_addri高16位丢失。
核查2(无有效防护):无对 tail_num*sizeof(U)>16 的校验。
核查3(函数可达):entry_callchain 确认 ConcatExtendDyn(第548行)→ConcatExtend(第389行)→ScatterInputPadded(第307行)→GenMaskReg(第248行),call_sites 确认 ScatterInputPadded 第307行调用。
核查4(触发可满足):经 Grep 确认 concat_api_call.cpp 第300行 gather_mask_dim_sizes.emplace_back(last_dim_size),last_dim_size 来自张量末维大小(第297行),为外部可控输入。
函数注释'不对齐,必然有tail'确认专用于非对齐数据。
tail_num>8(U=uint16_t)或>4(U=uint32_t)覆盖约44%/38%的非对齐场景,如末维=10(U=uint16_t)时 tail_num=10, 10*2=20>16 截断。
触发条件可满足,缺陷确认。

数据流证据

Source(问题源头)

autofuse/v35/ascendc/api_regbase/concat.h:248 行 uint32_t gather_mask_dim_size 作为 GenMaskReg 函数入参传入,决定 tail_num 的值

Sink(问题爆发点)

autofuse/v35/ascendc/api_regbase/concat.h:256 行 const uint16_t tail_mask = (1U << (tail_num * sizeof(U))) - 1U 将 32 位计算结果赋值给 uint16_t,当 tail_num * sizeof(U) > 16 时高位被截断

传播路径:

# 文件 行号 说明
1 autofuse/v35/ascendc/api_regbase/concat.h 548 ConcatExtend<T, INPUT_NUM>(dst_addr, src_addrs, tmp_buf, tiling) ConcatExtendDyn 调用 ConcatExtend
2 autofuse/v35/ascendc/api_regbase/concat.h 389 ScatterInputPadded(..., tiling.src_row_strides[i], tiling.src_second_last_dim_strides[i], tiling.gather_mask_dim_sizes[i]) ConcatExtend 调用 ScatterInputPadded,传入 tiling.gather_mask_dim_sizes[i]
3 autofuse/v35/ascendc/api_regbase/concat.h 307 MicroAPI::MaskReg copy_in_mask = GenMaskReg(src_row_stride, gather_mask_repeat_stride, gather_mask_dim_size, tmp_buf_addr) ScatterInputPadded 调用 GenMaskReg
4 autofuse/v35/ascendc/api_regbase/concat.h 248 uint32_t gather_mask_dim_size 作为 GenMaskReg 函数入参传入
5 autofuse/v35/ascendc/api_regbase/concat.h 255 const uint16_t tail_num = gather_mask_dim_size % (32 / sizeof(U)) 计算 tail_num,取值范围为 0 到 (32/sizeof(U))-1
6 autofuse/v35/ascendc/api_regbase/concat.h 256 const uint16_t tail_mask = (1U << (tail_num * sizeof(U))) - 1U 1U 为 32 位无符号整数,移位结果为 32 位,赋值给 uint16_t 时高位截断(sink)
7 autofuse/v35/ascendc/api_regbase/concat.h 259 index_addr[i] = tail_mask 截断后的 uint16_t tail_mask 零扩展为 uint32_t 存入 index_addr,高 16 位丢失

调用链

可达调用链1 起点:(entry functions) → 终点:AscendC::MicroAPI::GenMaskReg 深度:3

# 文件 函数 函数起始行 调用点行
1 autofuse/v35/ascendc/api_regbase/concat.h ConcatExtendDyn 543 548
2 autofuse/v35/ascendc/api_regbase/concat.h ConcatExtend 361 389
3 autofuse/v35/ascendc/api_regbase/concat.h ScatterInputPadded 283 307
4 autofuse/v35/ascendc/api_regbase/concat.h:AscendC::MicroAPI: GenMaskReg 248

修复建议

const uint32_t tail_mask = (1U << (tail_num * sizeof(U))) - 1U;
likedislike
Wwangmingming成员
8月20日 将 gcw_V3YyYBt1 设为负责人
wangmingming成员
8月20日 评论:

你好,感谢建议, 后续分析处理

likedislike
m0_56712298m0_56712298
24 天前 关联了pull request:fix: 修复 Gather 回绕及 BrcInline/Cast/Concat 截断(#256 #258 #259 #260)
Wwangmingming成员
14 天前 issue状态由 进行中 改变为 已完成
Wwangmingming成员
14 天前 关闭了 issue