C++ 检查时间、使用时间问题,包括access()、faccessat()、stat()、lstat()、fstat()、open()和fopen()

C++ 检查时间、使用时间问题,包括access()、faccessat()、stat()、lstat()、fstat()、open()和fopen(),c++,linux,windows,fopen,c++98,C++,Linux,Windows,Fopen,C++98,我不经常在这里发帖,所以在我试图决定如何解决这个问题时,请容忍我 我正在更新一个代码库,这个代码库已经有10-20年没有被触及了。该代码是在没有遵循最佳实践的情况下编写的,许多作者有时对安全约定有不完全的理解,甚至可能在这些约定成为常见实践之前。此代码中使用的编译器是c++98或c++03,但不是最新版本。该代码也是Linux和Windows之间的跨平台代码 所有这些都说,我需要一些C++老兵的帮助,理解访问()、Stand()和Open-()的正确用法及其与ToToTo问题有关的变态。 以下是

我不经常在这里发帖,所以在我试图决定如何解决这个问题时,请容忍我

我正在更新一个代码库,这个代码库已经有10-20年没有被触及了。该代码是在没有遵循最佳实践的情况下编写的,许多作者有时对安全约定有不完全的理解,甚至可能在这些约定成为常见实践之前。此代码中使用的编译器是c++98或c++03,但不是最新版本。该代码也是Linux和Windows之间的跨平台代码

所有这些都说,我需要一些C++老兵的帮助,理解访问()、Stand()和Open-()的正确用法及其与ToToTo问题有关的变态。 以下是说明TOCTOU问题的示例代码块:

#ifdef WIN32
    struct _stat buf;
#else
    struct stat buf;
#endif //WIN32

    FILE *fp;
    char data[2560];

    // Make sure file exists and is readable
#ifdef WIN32
    if (_access(file.c_str(), R_OK) == -1) {
#else
    if (access(file.c_str(), R_OK) == -1) {
#endif //WIN32

        /* This is a fix from a previous 
           Stack-based Buffer Overflow
           issue.  I tried to keep the original
           code as close to possible while
           dealing with the potential security
           issue, as I can't be certain of how
           my change might effect the system. */

        std::string checkStr("File ");
        checkStr += file.c_str();
        checkStr += " Not Found or Not Readable";
        if(checkStr.length() >= 2560)
            throw checkStr.c_str();

        char message[2560];
        sprintf(message, "File '%s' Not Found or Not Readable", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
        }

    // Get the file status information
#ifdef WIN32
    if (_stat(file.c_str(), &buf) != 0) {
#else
    if (stat(file.c_str(), &buf) != 0) {
#endif //WIN32

        /* Same story here. */

        std::string checkStr("File ");
        checkStr += file.c_str();
        checkStr += " No Status Available";
        if(checkStr.length() >= 2560)
            throw checkStr.c_str();

        char message[2560];
        sprintf(message, "File '%s' No Status Available", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
        }

    // Open the file for reading
    fp = fopen(file.c_str(), "r");
    if (fp == NULL) {
        char message[2560];
        sprintf(message, "File '%s' Cound Not be Opened", file.c_str());
        //DISPLAY_MSG_ERROR( this, message, "GetFileContents", "System" );
        throw message;
    }

    // Read the file
    MvString s, ss;
    while (fgets(data, sizeof(data), fp) != (char *)0) {
        s = data;
        s.trimBoth();
        if (s.compare( 0, 5, "GROUP" ) == 0) {
            //size_t t = s.find_last_of( ":" );
            size_t t = s.find( ":" );
            if (t != string::npos) {
                ss = s.substr( t+1 ).c_str();
                ss.trimBoth();
                ss = ss.substr( 1, ss.length() - 3 ).c_str();
                group_list.push_back( ss );
            }
        }
    }

    // Close the file
    fclose(fp);
}
如您所见,以前的开发人员希望确保用户有权访问“文件”,将“文件”stat-ed,然后在不重新访问()的情况下打开它,并且在fopen()之后也不重新stat()-ing“文件”。我理解为什么这是一个TOCTOU问题,但我不知道如何解决它

根据我的研究,open()比fopen()更受欢迎,fstat()比stat()更受欢迎,但是lstat()在哪里合适呢?如果我做一个统计,我需要access()或faccessat()吗

更重要的是,这需要与Windows编译器兼容,我发现有文章说fopen()更好,因为它是跨平台的,而open()不是,这使得open()可能无法使用;这对于stat()和access()的变体似乎也是一样的,但我不确定


如果你已经走到这一步,谢谢你阅读所有内容,我欢迎对这篇文章的任何批评和帮助

我发现有文章说fopen()更好,因为它是跨平台的,而open()不是
,这是正确的。对于某些用例,特定于平台的功能可能是唯一(可能/可接受)的解决方案,但如果fopen能够完成这项工作,则总是更喜欢它。就个人而言,我会放弃对access和stat的调用,因为它们似乎没有做任何有用的事情。代码甚至不需要使用stat返回的数据!这些例外情况真的有效吗?它们似乎返回了一个指针,用于删除(由于堆栈展开)本地缓冲区。我不确定这些异常是否真的有效。我是这个系统的新手,他们似乎从来没有对这些例程进行过单元测试。access和stat调用仅在if语句中用于检查文件是否在用户权限内,以及文件是否确实存在。如果它们返回failure,则会引发某种异常。这就是为什么这些都需要重新编写的原因。