C 这会导致溢出吗?

C 这会导致溢出吗?,c,string,overflow,C,String,Overflow,下面是一段代码,我认为它可能导致readlink()函数溢出 pid_t get_pid_from_proc_self() { char buffer[4]; pid_t pid; readlink("/proc/self", buffer, sizeof(buffer)); sscanf(buffer, "%d",(int *)&pid); return pid; } 由于在Linux中PID为4字节,readlink()将“/proc/

下面是一段代码,我认为它可能导致readlink()函数溢出

pid_t get_pid_from_proc_self()
{
    char buffer[4];
    pid_t pid;

    readlink("/proc/self", buffer, sizeof(buffer));

    sscanf(buffer, "%d",(int *)&pid);

    return pid;
}
由于在Linux中PID为4字节,
readlink()
将“/proc/self”中的32位复制到
target[]
。然后,根据我的说法,应该为
'\0'
使用一个额外的字节,即5个字节


另外,
readlink()
是否会在字符串末尾自动插入
'\0'
,或者我是否必须将其指定给最后一个字节?

根据此处显示的示例:

编辑:

我想知道:

因为在Linux中PID是4字节,所以readlink()从“/proc/self”复制32位


难道你没有得到PID的字符串版本,而不是实际的4字节整数吗?您的值不能达到10位吗?5位数?(关于max proc value远小于max 4字节int value的评论-谢谢@Karl)

不,它不会导致溢出。它最多读取
sizeof(buffer)
字节,然后停止。它不会以null结尾字符串,因此您必须这样做。在确保最后一个字节为
\0
之前读取
缓冲区将导致未定义的行为(这是
sscanf()
调用正在执行的操作)。

readlink不会溢出,因为它不会将'\0'放在末尾。但sscanf会的。您应该这样做:

char buf[5];
ssizet_t len;
...
if ((len = readlink("/proc/self", buf, sizeof(buf)-1)) != -1)
    buf[len] = '\0';
您应该这样做:

char buf[5];
ssizet_t len;
...
if ((len = readlink("/proc/self", buf, sizeof(buf)-1)) != -1)
    buf[len] = '\0';
readlink()
不会导致溢出,但不会追加尾部的
\0
sscanf()
可能会造成严重伤害(缓冲区溢出)。从
readlink()
手册页

readlink()放置 缓冲区buf中的符号链接路径, 它的尺寸是bufsiz。readlink()可以 不向buf追加空字节。会的 截断内容(长度为 bufsiz字符),以防缓冲区 太小了,装不下所有的 内容


此外,
readlink()
读取PID的文本,该文本可以大于
“9999”
。仅使用四个字节在文本中存储PID值是不够的。

您的假设完全不正确
sizeof(pid_t)
为4并不意味着需要4个字节来存储表示数字的十进制字符串。典型的16位pid(如12345)显然需要6个字节才能存储为字符串,如果Linux已配置为允许32768个以上的进程,则很容易会更长

foo\u t
整数类型作为十进制字符串保存的缓冲区的正确大小是
3*sizeof(foo\u t)+2
。如果您愿意的话,您可以在边界上做得稍微好一点,但是我不介意为了源代码的简单性(和明显的正确性)而浪费一些字节


(注意,我假设8位字节,这是POSIX所需要的,因为PID是POSIX的概念。如果您想支持更大的字节,您需要使用
CHAR\u-bit
)调整绑定)

问题是关于
readlink()
。我添加了一条关于在确保字符串以null结尾之前读取字符串的注释,以解决
sscanf
问题,尽管没有明确说明。我将这样做。因此
sscanf()
函数将把PID+'\0'复制到
PID
变量中,并导致溢出。我说得对吗?sscanf不知道缓冲区只有4个字符长,所以它会一直超过结尾。如果我
Nul
终止字符串,并在第5个字节终止字符串,那么
sscanf()
将复制4个字节或5个字节:PID+'\0'?它不会“复制”它,但是的,它会做你想做的事情。实际上,对于
/proc/sys/kernel/pid_max
的大多数常见值来说,它更像是一个5字节的字符串(我的最大值是32768),但是+1用于注意字符串和int之间的差异。@Karl-crap我知道(曾经),但我想我的头脑因为没有使用而变得一团糟+谢谢你的评论,谢谢大家的评论!很难接受一个答案。所以我选择了第一个注意到sscanf()将溢出的用户的答案+)学习新东西感觉真好。