我有以下代码,我认为它会导致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()
将32位从“/ proc / self”复制到target[]
。然后,根据我的说法,'\0'
应该使用一个额外的字节,这使得它成为5个字节。
此外,readlink()
是否会在结尾处自动插入'\0'
字符串,还是必须将其专门分配给最后一个字节?
答案 0 :(得分:3)
不,它不会导致溢出。它将读入最多sizeof(buffer)
个字节,然后停止。它不会终止你的字符串,所以你必须这样做。在确保最后一个字节为buffer
之前阅读\0
将导致未定义的行为(这是您的sscanf()
调用正在进行的操作)。
答案 1 :(得分:2)
根据此处显示的示例:
http://pubs.opengroup.org/onlinepubs/009695399/functions/readlink.html
if ((len = readlink("/modules/pass1", buf, sizeof(buf)-1)) != -1)
buf[len] = '\0';
编辑:
我想知道:
由于在Linux中PID是4字节,readlink()从“/ proc / self”复制32位......
你不回来PID的字符串版本,而不是一个实际的4字节整数?你的价值难以达到 10位? 5位数? (关于最大过程值的评论远远小于最大4字节的内部值 - 感谢@Karl)
答案 2 :(得分:1)
readlink不会溢出,因为它不会将'\ 0'放在最后。但是sscanf会。你应该这样做:
你应该这样做:
char buf[5];
ssizet_t len;
...
if ((len = readlink("/proc/self", buf, sizeof(buf)-1)) != -1)
buf[len] = '\0';
答案 3 :(得分:1)
readlink()
不会导致溢出,但它不会追加尾随\0
和sscanf()
可能会造成严重损害(缓冲区溢出)。来自readlink()
联机帮助页。
readlink()放置的内容 缓冲区中的符号链接路径, 其大小为bufsiz。 readlink()的确如此 不向buf附加空字节。它会 截断内容(长度为 bufsiz字符),以防缓冲区 太小了,无法容纳所有人 内容。
此外,readlink()
读取PID的文本,该文本可能大于"9999"
。仅使用四个字节将PID值存储在文本中是不够的。
答案 4 :(得分:1)
你的假设是完全偏离基础的。 sizeof(pid_t)
为4并不意味着需要4个字节来存储表示数字的十进制字符串。典型的16位pid(如12345)显然需要6个字节作为字符串存储,如果Linux已配置为允许超过32768个进程,则可能会更长。
将foo_t
整数类型保存为十进制字符串的缓冲区的正确大小为3*sizeof(foo_t)+2
。如果你愿意的话,你可以在边界上做得稍微好些,但我不介意在源代码中为了简单(和明显的正确性)而浪费几个字节。
(注意我假设8位字节,POSIX需要,因为pids是POSIX概念。如果你想支持更大的字节,你需要使用CHAR_BIT
来调整边界。)< / p>