尽可能安全地在c中打开文件

时间:2013-11-30 19:00:57

标签: 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;
} 

在打开文件之前或之后,我还需要确认其他检查吗?

如果打开文件可能会损坏系统(病毒)怎么办?有什么检查吗?

如果文件不是.txt文件,用户只是将mp3文件重命名为txt文件怎么办?

4 个答案:

答案 0 :(得分:3)

无需其他检查。

我总是把它作为调用fclose的做法,但是,当完成文件*时。

答案 1 :(得分:2)

模式r应仅用于打开文本文件。不同的系统具有不同的存储文本的方式,并且该模式将相应地自动翻译文件。例如,DOS / Windows使用\r\n表示新行,类UNIX系统使用\n,MAC使用\r以及其他可能的差异。

要真实地打开和阅读文件,在二进制安全模式中,您应该使用rb

此模式使您可以完全控制要写入二进制级别的内容,并且是读取和写入二进制数据(如struct转储,加密信息等)的唯一安全方法。

答案 2 :(得分:1)

  打开文件后

在打开文件时要小心,在阅读,编写和关闭文件时也应如此。因此,请务必检查所涉及的电话的结果。

答案 3 :(得分:0)

我认为这是一个老问题。但是:

您可以进行一些其他安全检查,以验证您正在打开的是真实文件,而不是符号链接。

原因:通过链接到另一个文件替换文件是一种已知的攻击技术(与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,则该文件不是常规文件。不要打开它。

另外,请阅读here