【问题标题】:Overflow not detected when writing nul character in middle of string?在字符串中间写入空字符时未检测到溢出?
【发布时间】:2015-02-09 02:15:15
【问题描述】:

假设我有代码:

char* word  = malloc (sizeof(char) * 6);
strcpy(word, "hello\0extra");
puts(word);
free(word);

这个编译只是find,Valgrind没有问题,但是真的有问题吗?好像我正在写入我不拥有的记忆。

另外,一个单独的问题,但是当我用类似的东西填满缓冲区时

char* word  = malloc (sizeof(char) * 6);
strcpy(word, "1234567\0");
puts(word);
free(word);

它打印出 1234567 并且 Valgrind 确实发现了问题。做这样的事情会有什么后果?它似乎每次都有效。如果这是错误的,请纠正我,但据我了解,另一个程序有可能将内存超过 6 并写入它。如果发生这种情况,打印这个词会永远持续下去,直到遇到一个 nul 字符?在学习 C 字符串时,这个字符让我非常困惑。

【问题讨论】:

  • 哦,唯一真正的问题是你会得到一个讨厌的 NASAL DEAMONS 案例。
  • strcpy(word, "hello\0extra"); 将在第 6 个字符(终止符)之后停止,所以这个人为的例子没有问题。
  • 您的第二个问题,strcpy 会将您告诉它的任何内容复制到溢出空间,只要它不会导致段错误。这是否会破坏某些东西,取决于它覆盖了什么。假设它会破坏某些东西。

标签: c buffer-overflow strcpy


【解决方案1】:

您的第一个问题已经有了几个很好的答案。关于第二个问题,关于在分配内存末尾写入一个字节的后果:

mallocing 6 个字节并写入 7 会导致崩溃是值得怀疑的。 malloc 喜欢在某些边界上对齐内存,因此不太可能在页面末尾给你六个字节,这样在字节 7 就会出现访问冲突。但是如果你 malloc 65536 字节并尝试写到最后,你的程序可能会崩溃。写入无效内存很多时候都有效,这使得调试变得很棘手,因为只有在某些情况下才会随机崩溃。

【讨论】:

    【解决方案2】:

    第一次调用strcpy 时,NUL 被插入到字符串的中间。这意味着处理以 null 结尾的字符串的函数会将您的字符串视为以第一个 NUL 停止,而忽略字符串的其余部分。但是,free 将释放所有这些,而 valgrind 不会报告问题,因为malloc 会将缓冲区的长度存储在分配表中,free 将使用该条目来确定要释放多少字节。换句话说,malloc 和free 并不是要处理以空字符结尾的字符串,所以字符串中间的NUL 不会影响它们。相反,free 根据您首先分配的字节数确定字符串的长度。

    在第二个示例中,您溢出了由malloc 分配的缓冲区的末尾。结果是不确定的。从理论上讲,您正在写入的内存可能已通过另一个调用 malloc 分配,但在您的示例中,缓冲区之后的内存没有做任何事情,因此它是无害的。字符串处理函数认为您的字符串以第一个 NUL 结尾,而不是以 malloc 分配的缓冲区结尾,因此所有字符串都被打印出来。

    【讨论】:

    • 也许只有我一个人,但这似乎不是特别清楚。 malloc 和 free 不在乎内存中的内容; free 将释放分配的六个字节。 strcpy 只将hello\0 写入word,因此extra 将只存在于程序的字符串表中——它永远不会被复制到任何地方。
    【解决方案3】:
    strcpy(word, "hello\0extra");
    

    这是有效的,因为第二个参数应该是一个格式良好的字符串,这是因为你有一个 \0 作为你的第 6 个字符,它形成了一个长度为 5 的字符串。

    strcpy(word, "1234567\0");
    

    在这里,您正在访问不属于您/未分配的内存,因此这是访问冲突并可能导致崩溃。(段错误)

    【讨论】:

      【解决方案4】:

      第一个strcpy就可以了

      strcpy(word, "hello\0extra");
      

      您创建一个char 数组常量并将指针传递给strcpy。复制所有字符(包括第一个 \0),忽略其余字符。

      但是等等……你还有一些额外的字符。这使您的 const 数据部分更大一些。在闪存空间很少的嵌入式环境中可能是一个问题。但不存在运行时问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-07
        • 2014-08-16
        • 2012-02-02
        • 2013-11-11
        • 1970-01-01
        相关资源
        最近更新 更多