0

有谁知道为什么会发生这种情况?

我在 AIX 5.3 中有一个 C 程序,有人要求我在 SPARC Solaris 10 机器上运行它,但是当我这样做时,我注意到有一个缓冲区溢出,其中一种是不计后果的 strcat 使用。我的目标不是清理代码,而是提供一个具体而有根据的答案,说明为什么这种溢出发生在 Solaris 而不是 AIX 上是完全相同的错误编码程序。

我一直在阅读一些关于这是否可能是由以下原因引起的:

  1. AIX 和 Solaris 之间的字节序差异。

  2. 执行 strcat 函数(AIX 从右到左复制,Solaris 从左到右复制),但我找不到任何关于此的文档。

  3. 很幸运,这个问题在 AIX 上没有发生。

非常感谢您对此有所了解。

编辑:可以通过solaris 上的 noexec_user_stack 标志避免这种情况吗?

编辑 2: 有没有人知道两个操作系统进行实际字节复制的方式?在类似于上述选项 2 的情况下?

编辑3:这是代码块:

/*global*/
char bufferA[101];
/*inside function*/
bufferA[0]='\0';
strcpy(bufferA,"1");
if (atoi(something)==0) {
strcat(bufferA,pieces_of_data);
count ++ ;
}

显然还有更多,但这是唯一使用bufferA的部分,并且在bufferA之后声明了2个全局变量,这些变量被附加到bufferA的最后一个字符串的最后一部分损坏。

正如我之前所说,如果我将声明从 101 更改为 201,则不会发生腐败。

编辑 4:有人知道关于 solaris 上的 -misalign 和 -misalign2 编译器选项吗?这些选项有什么亮点吗?实际上,一个更好的问题是:AIX powerPC 和 Solaris SPARC 在对齐方面有什么区别吗?尽管这可能是 serverfault 的问题,但如果您知道的话,请分享。

4

5 回答 5

2

这要么是(坏?)运气,要么可能是内存管理系统略有不同的产物,在 AIX 上分配的空间比在 Solaris 上多。

这部分取决于溢出的严重程度。如果它们超出界限,并且如果 AIX 习惯性地分配 32 字节最小块,而 Solaris 分配 16 字节最小块,那么在 AIX 上比在 Solaris 上更容易出错而不会造成损坏。即便如此,如果您在错误的上下文中弄错了,AIX 也应该有问题 - 您可以认为自己很不幸没有在 AIX 上观察到问题,因为正如您所说,它肯定会像它一样在那里发生如果您正在编译的源代码相同,则在 Solaris 上。

进一步调查显示:

  • 对于 32 位编译,AIX 5.3 为每个分配分配 16 个字节的倍数,就像 Solaris。
  • 对于 64 位编译,AIX 5.3 每次分配 32 字节的倍数;这也与 Solaris 相同。

但是,如果您在 AIX 和 Solaris 之间更改了 32 位和 64 位版本,这可能仍然是问题的根源。

无论答案是什么,现在您都知道了,通过一组更改为两个平台修复它。你对每一个暴露的虫子都心存感激;在任何时候,对原始平台的更改都可能会暴露问题 - 导致客户不满意的重大问题。

(哦,我认为 SPARC 和 PPC 都是大端机器;英特尔是小端机器,与世界其他地方不同。)


测试代码 - 故意、故意泄漏

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
    int sz ;
    char *buffer;
    for (sz = 1; sz < 1025; sz *= 2)
    {
        buffer = malloc(sz);
        printf("0x%08lX\n", (unsigned long)buffer);
    }   
    return 0;
} 
于 2010-09-23T17:49:30.033 回答
2

如果它发生在一个平台上,它就会发生在另一个平台上。您很幸运,一个平台上的内存布局导致错误显现。

这是未定义的行为

如果你有一堆无人看管的strcpy/cats乱扔你的代码,请修复代码。不要责怪平台。怪作者。

Valgrind是你的朋友。

于 2010-09-23T19:13:03.047 回答
0

我不确定这是否算作一个答案,但一个快速而肮脏的解决方法可能是用 搜索和替换malloc代码中的所有实例workaround_malloc,并将后者实现为对malloc(size+100).. 的调用:- )

于 2010-09-23T19:02:10.453 回答
0

这可能是该错误的处理器依赖表现。数据的填充和对齐通常都由目标处理器的特性决定。额外的填充字节可能会在一个目标上隐藏错误,而在另一个目标上填充字节较少。

它还可能与传递 strcat 的实际数据不同有关。例如,如果它正在构建的字符串的一部分由操作系统名称、处理器或系统文件的路径组成。

也可能是字符串分配的大小基于标头常量或sizeof不同目标的不同大小,因此您的实际缓冲区更小。

我可能会尝试的一件事是让编译器为每个目标生成源文件的预处理版本并区分它们。它们在初始标头代码中可能会有很大不同,但在您的代码所在的末尾应该大部分相似。查看该代码中是否存在任何可疑差异。遗憾的是sizeof,这里不会被数字取代,但宏常量会被取代。

于 2010-09-23T19:14:17.223 回答
0

以下是使用 Solaris Studio 调试器查找内存访问/使用错误的方法:

1: Download studio
  http://www.oracle.com/technetwork/server-storage/solarisstudio/overview/index.html
2: Install it
  Uncompress/Extract the downloaded file somewhere in your disk
  Run the installer
3: Recompile your program with debugging on
  $ PATH=$PATH:/opt/<studio-installation-directory>/bin
  $ cc -g program.c
4: Launch your program under debugger control
  $ dbx program
5: Enable run time checking
  (dbx) check -all
  access checking - ON
  memuse checking - ON
6: Run your program
  (dbx) run
7: Watch all the error messages
  ...
于 2010-09-28T07:57:46.183 回答