代码之家  ›  专栏  ›  技术社区  ›  Alphaneo

C中的字符串溢出检测

  •  3
  • Alphaneo  · 技术社区  · 16 年前

    我们正在使用devpartners boundchecker检测内存泄漏问题。它做得很好,尽管它没有发现字符串溢出,如下所示

    char szTest [1] = "";
    
    for (i = 0; i < 100; i ++) {
    
        strcat (szTest, "hi");
    }
    

    问题1:他们有什么办法吗,我可以让边界检查器检测到这一点?

    问题2:他们的其他工具是否可以检测到这些问题?

    8 回复  |  直到 15 年前
        1
  •  2
  •   EvilTeach    16 年前

    我在我的devpartner(msvc6.6)中尝试过(devpartner 7.2.0.372)

    我确认你观察到的行为。 在循环经过大约63次之后,我得到了一个访问冲突。

    电脑软件对这个问题有什么看法?

    CppCheck 将检测到此问题。

        2
  •  2
  •   Michael Burr    16 年前

    一种选择是简单地禁止使用没有目标缓冲区信息的字符串函数。在一个通用的包含头文件中,像下面这样的一组宏可能会有所帮助:

    #define strcpy  strcpy_is_banned_use_strlcpy
    #define strcat  strcat_is_banned_use_strlcat
    #define strncpy strncpy_is_banned_use_strlcpy
    #define strncat strncat_is_banned_use_strlcat
    #define sprintf sprintf_is_banned_use_snprintf
    

    因此,任何试图使用“禁止”例程的操作都会导致链接器错误,该错误还会告诉您应该使用什么。MSVC做了类似的事情,可以使用宏来控制 _CRT_SECURE_NO_DEPRECATE .

    这种技术的缺点是,如果您有一大组现有的代码,那么将这些代码转移到使用新的、更安全的例程上可能是一项巨大的工作。它会让你疯狂,直到你摆脱那些被认为是危险的功能。

        3
  •  2
  •   Alok Singhal    16 年前

    valgrind 将检测到写入过去动态分配的数据,但我认为它不能像您的示例中那样对自动数组这样做。如果您正在使用 strcat , strcpy 等等,你必须确保目的地足够大。

    编辑 我是 right about valgrind 但仍有希望:

    不幸的是,memcheck不在静态数组或堆栈数组上执行边界检查。我们很想这样做,但不可能用一种符合memcheck工作原理的合理方式。对不起的。

    然而,实验工具ptrcheck可以检测这样的错误。和Valgrind一起跑 --tool=exp-ptrcheck 尝试它的选择,但要注意它不如memcheck那么健壮。

    我没有使用ptrcheck。

        4
  •  1
  •   Steve314    16 年前

    您可能会发现编译器有帮助。例如,在VisualStudio 2008中,检查项目属性-C/C++代码生成页。有一个“缓冲区安全检查”选项。

    我的猜测是它会保留一些额外的内存,并在其中写入一个已知的序列。如果该序列被修改,则假定缓冲区溢出。不过,我不确定——我记得在某个地方读过这篇文章,但我不确定它是否与VC++有关。

        5
  •  1
  •   Jerry Coffin    16 年前

    既然你已经标记了这个C++,为什么要使用一个指向char的指针呢?

    std::stringstream test;
    std::fill_n(std::ostream_iterator<std::string>(test), 100, "hi");
    
        6
  •  1
  •   Mark Wilkins    16 年前

    如果启用 /RTCs compiler switch 可能有助于解决此类问题。打开此开关时,测试在运行 strcat 只有一次。

    另一个有用的实用工具可以帮助解决像这样的问题(比堆栈更面向堆,但非常有用)。 application verifier . 它是免费的,可以捕获许多与堆溢出相关的问题。

        7
  •  0
  •   Ira Baxter    15 年前

    另一种选择:我们的 Memory Safety Checker . 我想它能处理这个案子。

        8
  •  0
  •   Rick Papo    15 年前

    问题是,默认情况下,API验证子系统未启用,您感兴趣的消息来自该子系统。

    我不能用旧版本的boundschecker说话,但是10.5版在这个测试中没有特别的问题。它报告正确的结果,boundchecker本身不会崩溃。然而,测试应用程序确实这样做了,因为这个特定的测试用例完全破坏了导致测试代码所在函数的调用堆栈,一旦该函数终止,应用程序也会这样做。

    结果:100条关于向局部变量写入溢出的消息,以及99条关于目标字符串非空终止的消息。从技术上讲,第二条消息是不对的,但是boundsChecker只在目标字符串本身的边界内搜索空终止,并且在第一次strcat调用之后,它在其边界内不再包含零字节。

    免责声明:作为一名开发人员,我为Microfocus工作,负责BoundsChecker。