C read()-如果在包含递归循环的循环中使用,请检查缓冲区边界

C read()-如果在包含递归循环的循环中使用,请检查缓冲区边界,c,io,buffer-overflow,flawfinder,C,Io,Buffer Overflow,Flawfinder,我有这段代码,并使用Failinder运行它,在read()函数中得到以下输出: 如果在包含递归循环的循环中使用,请检查缓冲区边界 有人看到问题了吗 #include <stdlib.h> void func(int fd) { char *buf; size_t len; read(fd, &len, sizeof(len)); if (len > 1024) return; buf = malloc(len+1); read(fd, buf, len); b

我有这段代码,并使用Failinder运行它,在read()函数中得到以下输出:

如果在包含递归循环的循环中使用,请检查缓冲区边界

有人看到问题了吗

#include <stdlib.h>
void func(int fd)
{

char *buf;
size_t len;
read(fd, &len, sizeof(len));

if (len > 1024)
return;
buf = malloc(len+1); 
read(fd, buf, len); 
buf[len] = '\0';
}
#包括
无效函数(int-fd)
{
char*buf;
尺寸透镜;
读取(fd和len,sizeof(len));
如果(len>1024)
返回;
buf=malloc(len+1);
读取(fd、buf、len);
buf[len]='\0';
}

您应该检查
read()
的返回值,以了解调用
read()
是成功还是失败,或者
read()
是否被信号中断,然后设置
errno
。例如

ssize_t ret = read(fd, &len, sizeof len);
if( (ret == -1 || ret != sizeof len) {
   /* error handling @TODO */
}
最重要的是在这里

ret = read(fd, buf, len); /* read() may read less than len characters */ 
read()
返回读取的字节数,因此

buf[len] = '\0';
使用

示例代码

void func(int fd) { /* assume fd is a valid file descriptor */
        char *buf = NULL;
        size_t len;
        errno = 0; /* set this to 0 */
        ssize_t ret = read(fd, &len, sizeof len);
        if( (ret == -1 || ret != sizeof len) {
                /* error handling @TODO */
        }
        if (len > 1024) {
                return;
        }
        buf = malloc(len+1); 
        if(buf == NULL) {
                /* error handling @TODO */
        }
        ret = read(fd, buf, len);
        if(ret!=-1) {
                buf[ret] = '\0';
                /* do something with buf and free it once usage is done*/
        }       free(buf); /* free the buf */
        else { /* if read failed */
                free(buf); /* free the buf */
        }
}

我更关心的是,这如何完全忽略从
read
两次(以及
malloc
)返回的潜在错误。第一个特别重要,因为它可能使
len
不确定。不要违反;检查IO结果是否有错误。
read()
返回的结果可能比要求的要少。至少在第一种情况下是致命的。因此,只测试
-1
是不够的。而且
read()
返回
ssize\t
not
int
,如果不是在Windows上。如果(ret!=sizeof len){就可以三思了。在
ret>0和&ret
的任何情况下,人们都可以循环
read()
读取,直到读取
len的大小
字节。在
ret==-1&&(errno==EAGAIN | | errno==EINTR)的情况下也可以这样做
。我还观察到,即使是
ret==-1&&errno==EIO
也值得重试的罕见情况。这通常发生在从基于网络的文件系统读取时。@PerKristianGravdal这里
ssize\t ret=read(fd,&len,sizeof(len))
从文件中读取一个整数值,并存储在
len
中。如果读取的
len
值大于
1024
,则不要继续,从函数返回。
void func(int fd) { /* assume fd is a valid file descriptor */
        char *buf = NULL;
        size_t len;
        errno = 0; /* set this to 0 */
        ssize_t ret = read(fd, &len, sizeof len);
        if( (ret == -1 || ret != sizeof len) {
                /* error handling @TODO */
        }
        if (len > 1024) {
                return;
        }
        buf = malloc(len+1); 
        if(buf == NULL) {
                /* error handling @TODO */
        }
        ret = read(fd, buf, len);
        if(ret!=-1) {
                buf[ret] = '\0';
                /* do something with buf and free it once usage is done*/
        }       free(buf); /* free the buf */
        else { /* if read failed */
                free(buf); /* free the buf */
        }
}