C语言sprintf字符串终止错误:预期行为与原因问询
sprintf代码片段的预期行为与字符串终止错误分析
先看代码:
sprintf(workbuf, "(C)(0225,0181) %6.6s HDR REC BAD TRAN_SETL_FNUM, OFFSET %ld, LEN %ld, FILE=[%s/%s]", tranHdr->lu.source_path_name, offsetof(RTPN_HEADER_REC, tran_setl_fnum), sizeof(rtpn_hdr->tran_setl_fnum), pathPtr->inFileName, pathPtr->userFileName);
预期行为
这段代码的目标是生成一条格式化的错误日志,写入workbuf缓冲区:
- 开头固定输出
(C)(0225,0181)标识 - 截取
tranHdr->lu.source_path_name的前6个字符(不足6位时左侧补空格,超过6位时只取前6位) - 输出结构体成员
tran_setl_fnum在RTPN_HEADER_REC中的偏移量(由offsetof计算) - 输出
tran_setl_fnum成员的字节大小(由sizeof计算) - 最后拼接
pathPtr->inFileName和pathPtr->userFileName成路径,放在FILE=[]中 - 按照
sprintf的正常逻辑,会自动在workbuf末尾添加\0字符串终止符,保证结果是合法的C字符串
字符串终止错误的原因
常见的触发原因有三个:
参数类型不匹配导致解析错位
sizeof返回的是size_t类型,但格式化符用了对应long类型的%ld。在64位系统中,size_t是64位、long是32位,这种类型不匹配会让sprintf读取参数时栈位置偏移,后续的字符串参数pathPtr->inFileName、pathPtr->userFileName被错误解析,破坏内存结构,最终无法正常写入\0终止符。缓冲区空间不足引发溢出
如果workbuf的分配大小小于格式化后字符串的总长度,sprintf会直接越界写入,覆盖缓冲区后方的内存——这其中就包含原本要存放\0的位置,导致字符串没有合法终止符。输入字符串本身不合法
若tranHdr->lu.source_path_name是未以\0终止的字符数组,%6.6s读取时会越界访问内存,不仅会读到垃圾数据,还会干扰后续参数的解析流程,导致整个格式化过程出错,终止符无法正常写入。
内容的提问来源于stack exchange,提问作者jit
相关产品推荐
相关产品推荐

