You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何用memcpy复制指定缓冲区后,sprintf输出字符数超出原缓冲区长度

问题原因分析

这个现象的本质是C语言的字符串要求必须以'\0'(空字符)作为结束标志,你的代码中多处字符串操作没有遵守这个规则,触发了未定义行为,不同输入下表现不同。

核心逻辑拆解

你的代码中存在两个关键的错误操作:

  • memcpy(smallbuf, input, 8):smallbuf是长度为8的字符数组,你直接复制8字节内容到数组中,没有预留位置存储'\0'结束符,也没有手动追加结束符。
  • sprintf(newbuf, "%s", smallbuf):%s格式符要求对应的参数是合法的以'\0'结尾的C字符串,如果没有结束符,sprintf会持续读取smallbuf后续内存地址的内容,直到遇到随机的'\0'才会停止,这个过程会把多余的内容也写入newbuf,打印时就会出现超出输入长度的内容。

不同输入的表现解释

输入7个字符的场景

input数组初始化时被全量置为'\0',当你输入7个字符(含回车共8字节)时,你复制到smallbuf的8字节内容之后紧邻的内存刚好是input数组剩下的初始'\0',所以sprintf读取时很快就遇到结束符,表现和预期一致。

输入8个字符的场景

当你输入8个可打印字符时,复制到smallbuf的8字节全是可打印字符,没有'\0'结束符。sprintf读取时会继续向后读取栈上的其他内容(大概率是input数组里的输入内容本身),直到遇到内存中随机出现的'\0'才停止,所以最终打印的内容会出现重复、长度超出输入的情况,极端情况下甚至会触发程序崩溃。

额外的代码问题提示

你的代码还存在两个严重的安全风险:

  • 直接调用printf(input)属于格式化字符串漏洞,如果用户输入包含%s/%x这类格式控制符,会导致内存泄露甚至代码执行,应该修改为printf("%s", input)。
  • sprintf不会检查目标缓冲区的长度,极易触发缓冲区溢出漏洞,应该替换为带长度限制的snprintf。

内容的提问来源于stack exchange,提问作者binarytrails

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:39:03