尽可能安全地在c中打开文件
我会写一个程序如下尽可能安全地在c中打开文件,c,file,error-handling,fopen,C,File,Error Handling,Fopen,我会写一个程序如下 int main () { FILE *fp = fopen("test.txt", "r") if (fp == NULL) { printf("Sorry, file doesn't exist."); return 0; } return 0; } 在打开文件之前或之后,是否需要进行其他检查 如果打开文件会损坏系统(病毒),该怎么办?有支票吗 如果文件不是
int main ()
{
FILE *fp = fopen("test.txt", "r")
if (fp == NULL)
{
printf("Sorry, file doesn't exist.");
return 0;
}
return 0;
}
在打开文件之前或之后,是否需要进行其他检查
如果打开文件会损坏系统(病毒),该怎么办?有支票吗
如果文件不是.txt文件,用户刚刚将mp3文件重命名为txt文件,该怎么办?无需其他检查
我还经常调用
fclose
,但是,当处理完文件*时,模式r
应仅用于打开文本文件。不同的系统有不同的文本存储方式,此模式将相应地自动翻译文件。例如,DOS/Windows使用\r\n
表示新行,类似UNIX的系统使用\n
,MAC使用\r
以及其他可能的区别
要按原样打开和读取文件,请在二进制安全模式下使用rb
此模式可让您完全控制写入二进制级别的内容,是读取和写入二进制数据(如struct
dumps、加密信息等)的唯一安全方法
打开文件后
打开文件时要小心,读、写和关闭文件时也要小心。所以,一定要检查相关电话的结果,这样做。我发现这是一个老问题。然而: 您可以执行一些额外的安全检查,以验证您正在打开的是真实的文件,而不是符号链接 原因:用指向另一个文件的链接替换文件是已知的攻击技术之一(与CWE-362相关)。 该文件可以替换为指向工程文件的链接,该工程文件包含一个序列,该序列应该攻击/崩溃您的应用程序,而不是预期的文件 因此,最佳做法是添加如下代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/* Return: 0 if file is a regular file, -1 if not */
static int test_file_type(const char *file)
{
struct stat st;
if (0 != lstat(file, &st)) {
fprintf(stderr, "lstat failed, probably no such a file\n");
perror("lstat");
return (-1);
}
if (S_IFREG != (st.st_mode & S_IFMT)) {
fprintf(stderr, "Error on file [%s] opening: not a regular file, but ", file);
switch (st.st_mode & S_IFMT) {
case S_IFSOCK:
fprintf(stderr, "socket\n");
break;
case S_IFLNK:
fprintf(stderr, "symbolic link\n");
break;
case S_IFBLK:
fprintf(stderr, "block device\n");
break;
case S_IFDIR:
fprintf(stderr, "directory\n");
break;
case S_IFCHR:
fprintf(stderr, "character device\n");
break;
case S_IFIFO:
fprintf(stderr, "FIFO\n");
break;
}
return (-1);
}
return (0);
}
#包括
#包括
#包括
/*返回:如果文件是常规文件,则返回0;如果不是,则返回-1*/
静态整型测试文件类型(常量字符*文件)
{
结构统计;
如果(0!=lstat(文件(&st)){
fprintf(stderr,“lstat失败,可能没有这样的文件\n”);
佩罗尔(“lstat”);
返回(-1);
}
如果(S_IFREG!=(st.st_模式和S_IFMT)){
fprintf(stderr,“打开文件[%s]时出错:不是常规文件,而是”,文件);
开关(st.st\U模式和S\U IFMT){
案例S_IFSOCK:
fprintf(stderr,“socket\n”);
打破
案例S_IFLNK:
fprintf(stderr,“符号链接”);
打破
案例S_IFBLK:
fprintf(stderr,“块设备”);
打破
案例S_IFDIR:
fprintf(stderr,“目录\n”);
打破
案例S_IFCHR:
fprintf(stderr,“字符设备”);
打破
案例S_IFFO:
fprintf(标准“先进先出”);
打破
}
返回(-1);
}
返回(0);
}
如果此函数返回<0,则该文件不是常规文件。不要打开它
另外,请阅读@cygwinnian我想知道为什么面试官会问这样一个简单的问题——你的错误信息可能会误导人。它表示该文件不存在,即使该文件存在,但当前用户没有打开该文件的权限。更好的错误:
fprintf(stderr,“错误:无法打开%s进行读取:%s\n”、“test.txt”、strerror(errno))
。如果在发生致命错误时从main
返回一个非零值(或使用非零退出代码调用exit
),则可以使程序更有用。如果打开文件会损坏系统(病毒),该怎么办?有支票吗?如果文件不是.txt文件,用户刚刚将mp3文件重命名为txt文件,该怎么办?如果打开文件会损坏系统(病毒),该怎么办?有支票吗?如果文件不是.txt文件,用户刚刚将mp3文件重命名为txt文件,该怎么办?如果是二进制文件,请使用rb
打开它<代码>r
用于文本文件。我不认为在文件上使用r
调用fopen
会像病毒那样损坏系统。