为何sprintf拼接后的cmd变量输出为空?已确认相关参数有效值
分析sprintf拼接后cmd为空的原因
问题代码
static int call_apab_process() { static char *pcFnctnNm = "call_apab_process"; int rc = SUCCESS; char cmd[4000]; char pid[11]; char logDir[2000]; cmd[0] = '\0'; pid[0] = '\0'; logDir[0] = '\0'; dbg_indent(pcFnctnNm); dbg_print("Entering Into call_apab_process"); dbg_print("Print Parameters.."); dbg_print("MY_HOME :[%s]",getenv("MY_HOME")); dbg_print("SESSION_ID :[%ld]",pvsp_env->sessionid); sprintf(cmd,"%s/bin/GQ19apab_DB_auto.sh %ld",getenv("MY_HOME"),pvsp_env->sessionid); sprintf(pid,"0%ld",pvsp_env->sessionid); sprintf(logDir,"%s/tmp/db",getenv("MY_HOME")); dbg_print("cmd :[%s]",cmd); }
执行输出
Entering Into call_dadp_process Print Parameters.. MY_HOME :[/opt/apnp] SESSION_ID :[1054628118] cmd :[]
核心原因:pid缓冲区溢出覆盖了cmd变量
问题出在pid数组的缓冲区大小不足,导致sprintf越界写入,破坏了栈上相邻的cmd变量:
pid定义为char pid[11];,但要写入的内容是"0%ld",其中SESSION_ID的值是1054628118(10位数字),拼接后生成字符串"01054628118",共11个字符,加上C字符串必需的终止符\0,总共需要12字节的空间。- 栈上的局部变量通常按定义顺序从高地址到低地址排列,
cmd是第一个定义的数组,pid位于其下方(地址更低)。当sprintf向pid写入时,会越界写入1字节的\0到cmd的起始位置,将cmd[0]设置为\0,导致后续打印cmd时显示为空。
解决方案
- 增大pid缓冲区:将
pid的大小调整为至少12字节,确保能容纳完整字符串加终止符:char pid[12]; - 改用snprintf避免溢出:所有字符串拼接操作都用
snprintf替代sprintf,强制限制写入长度,从根源避免缓冲区溢出问题:snprintf(cmd, sizeof(cmd), "%s/bin/GQ19apab_DB_auto.sh %ld", getenv("MY_HOME"), pvsp_env->sessionid); snprintf(pid, sizeof(pid), "0%ld", pvsp_env->sessionid); snprintf(logDir, sizeof(logDir), "%s/tmp/db", getenv("MY_HOME")); - 验证方法:暂时注释掉
sprintf(pid,...)这一行,重新运行程序,若cmd能正常输出内容,即可确认是pid溢出导致的问题。
内容的提问来源于stack exchange,提问作者Vimal Bhaskar
相关产品推荐
相关产品推荐

