strndup 调用正在破坏堆栈帧

发布于 2024-08-18 21:00:17 字数 432 浏览 13 评论 0 原文

我在 AIX 5.3 和 6.1 上看到了“strndup”调用的奇怪行为。 如果我调用 strndup 的大小大于实际源字符串长度的大小,则该调用后会出现堆栈损坏。

以下是可能出现此问题的示例代码:

int main ()
{
    char *dst_str = NULL;
    char src_str[1023] = "sample string";

    dst_str = strndup(src_str, sizeof(src_str));

    free(dst_str);
    return 0;
}

有人经历过这种行为吗?

如果是,请告诉我。

根据我的观察,操作系统中一定有一个补丁解决了这个问题。但我无法获得该补丁(如果有的话)。请照亮一些。

谢谢&问候, 图姆贝蒂

I have seen a strange behavior with "strndup" call on AIX 5.3 and 6.1.
If I call strndup with size more than the size of actual source string length, then there is a stack corruption after that call.

Following is the sample code where this issue can come:

int main ()
{
    char *dst_str = NULL;
    char src_str[1023] = "sample string";

    dst_str = strndup(src_str, sizeof(src_str));

    free(dst_str);
    return 0;
}

Does anybody have experienced this behavior?

If yes please let me know.

As per my observation, there must be a patch from OS where this issue got fixed. but i could not get that patch if at all there is any. Please throw some light.

Thanks & Regards,
Thumbeti

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

数理化全能战士 2024-08-25 21:00:17

您的代码中缺少 #include 。请尝试一下——我相当确定它会起作用。原因是,如果没有 #include ,作用域内就没有 strndup() 的原型,因此编译器会假设 strndup( ) 返回一个 int,并采用未指定数量的参数。这显然是错误的。 (我假设您正在 POSIX 兼容模式下进行编译,因此可以使用 strndup()。)

因此,在启用警告的情况下编译代码始终很有用。

如果更改后问题仍然存在,则可能存在错误。

编辑:看起来可能有一个 strndup() 的问题:问题似乎出在 AIX 上损坏的 strnlen() 函数中。如果即使在 #include 之后您仍看到问题,则您很可能遇到了该错误。 Google 搜索 显示一长串相关结果。

编辑2

您可以尝试以下程序并发布结果吗?

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
     char *test1   = "abcdefghijabcdefghijabcdefghijk";
     char *test2   = "012345678901234567890123456789";
     char *control = "01234567890123456789012345678";
     char *verify;
     free(strndup(test1, 30));
     verify = strndup(test2, 29); /* shorter then first strndup !!! */
     fprintf(stderr,">%s<\n",verify);
     if (strcmp(control, verify))
         printf("strndup is broken\n");
}

(取自 https://bugzilla.samba.org/show_bug.cgi?id =1097#c10。)

编辑 3:看到输出后,即 >01234567890123456789012345678<,且没有 strndup 损坏,我认为您的 AIX 版本没有 strndup bug。

最有可能的是你在某个地方破坏了内存(考虑到问题只在某些条件下出现在大型程序中)。您能制作一个小型、完整、可编译的示例来展示堆栈损坏问题吗?否则,您将必须调试程序中的内存分配/释放。有许多程序可以帮助您做到这一点,例如 valgrindvalgrindglibc mcheck, dmallocelectricfence 等。

You are missing a #include <string.h> in your code. Please try that—I am fairly sure it will work. The reason is that without the #include <string.h>, there is no prototype for strndup() in scope, so the compiler assumes that strndup() returns an int, and takes an unspecified number of parameters. That is obviously wrong. (I am assuming you're compiling in POSIX compliant mode, so strndup() is available to you.)

For this reason, it is always useful to compile code with warnings enabled.

If your problem persists even after the change, there might be a bug.

Edit: Looks like there might be a problem with strndup() on AIX: the problem seems to be in a broken strnlen() function on AIX. If, even after #include <string.h> you see the problem, it is likely you're seeing the bug. A google search shows a long list of results about it.

Edit 2:

Can you please try the following program and post the results?

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
     char *test1   = "abcdefghijabcdefghijabcdefghijk";
     char *test2   = "012345678901234567890123456789";
     char *control = "01234567890123456789012345678";
     char *verify;
     free(strndup(test1, 30));
     verify = strndup(test2, 29); /* shorter then first strndup !!! */
     fprintf(stderr,">%s<\n",verify);
     if (strcmp(control, verify))
         printf("strndup is broken\n");
}

(Taken from https://bugzilla.samba.org/show_bug.cgi?id=1097#c10.)

Edit 3: After seeing your output, which is >01234567890123456789012345678<, and with no strndup is broken, I don't think your version of AIX has the strndup bug.

Most likely you are corrupting memory somewhere (given the fact that the problem only appears in a large program, under certain conditions). Can you make a small, complete, compilable example that exhibits the stack corruption problem? Otherwise, you will have to debug your memory allocation/deallocation in your program. There are many programs to help you do that, such as valgrind, glibc mcheck, dmalloc, electricfence, etc.

迷途知返 2024-08-25 21:00:17

老话题了,不过我也遇到过这个问题。 AIX 6.1 上的一个简单测试程序结合 AIX 的 MALLOCDEBUG 证实了该问题。

#include <string.h>

int main(void)
{
     char test[32] = "1234";
     char *newbuf = NULL;

     newbuf = strndup(test, sizeof(test)-1);
}

编译并运行带有缓冲区溢出检测的程序:

~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)

现在运行 dbx 来分析核心:

~$  dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...

Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001        stbu   r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup@AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"

跟踪 strndup 中的指令,看起来它分配了一个缓冲区,该缓冲区的大小刚好足以处理 s 中的字符串加上 NULL 终止符。但是,它总是将 n 个字符复制到新缓冲区,必要时用零填充,如果 strlen(s) < 则导致缓冲区溢出。名词

char* strndup(const char*s, size_t n)
{
    char* newbuf = (char*)malloc(strnlen(s, n) + 1);
    strncpy(newbuf, s, n-1);

    return newbuf;
}

Old topic, but I have experienced this issue as well. A simple test program on AIX 6.1, in conjunction with AIX's MALLOCDEBUG confirms the issue.

#include <string.h>

int main(void)
{
     char test[32] = "1234";
     char *newbuf = NULL;

     newbuf = strndup(test, sizeof(test)-1);
}

Compile and run the program with buffer overflow detection:

~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)

Now run dbx to analyze the core:

~$  dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...

Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001        stbu   r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup@AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"

Tracing through the instructions in strndup, it appears that it mallocs a buffer that is just large enough to handle the string in s plus a NULL terminator. However, it will always copy n characters to the new buffer, padding with zeros if necessary, causing a buffer overflow if strlen(s) < n.

char* strndup(const char*s, size_t n)
{
    char* newbuf = (char*)malloc(strnlen(s, n) + 1);
    strncpy(newbuf, s, n-1);

    return newbuf;
}
初见终念 2024-08-25 21:00:17

阿洛克是对的。使用glibc下的gcc工具链,您需要定义_GNU_SOURCE来获取strndup的decl,否则它不会被decl'd,例如:

#include <string.h>
...

compilo:

gcc -D_GNU_SOURCE a.c

Alok is right. and with the gcc toolchain under glibc, you would need to define _GNU_SOURCE to get the decl of strndup, otherwise it's not decl'd, e.g.:

#include <string.h>
...

compilo:

gcc -D_GNU_SOURCE a.c
高冷爸爸 2024-08-25 21:00:17

非常感谢您的及时回复。
我已经尝试过给定的程序。

以下是结果:

bash-2.05b# ./mystrndup3
>01234567890123456789012345678<

在我包含的程序中,问题仍然存在。
以下是前置代码中的 strndup 声明。

extern char * strndup(const char *, size_t);

我想澄清一件事,对于小程序,我不会受到堆栈损坏的影响。它始终出现在我的产品中,该产品具有大量函数调用。

按以下方式使用 strndup 解决了问题:

dst_str = strndup(src_str, srtlen(src_str));

请注意:使用 strlen 而不是 sizeof,因为我只需要有效的字符串。
我试图理解为什么会发生这种情况。

当我使用大尺寸的 strndup 时,我在产品中看到的行为:

  1. 在 main 的“退出”处,执行以“非法指令”为核心,
  2. 在执行过程中间歇性地出现“非法指令”(在 strndup 调用之后)。
  3. 某些分配的内存损坏,这与 strndup 无关。

所有这些问题只需根据源字符串的实际大小修改 strndup 的使用即可解决。

谢谢&问候,
图姆贝蒂

Thanks a lot for your prompt responses.
I have tried the given program.

following is the result:

bash-2.05b# ./mystrndup3
>01234567890123456789012345678<

In my program I have included , still problem is persistent.
Following is the strndup declaration in prepossessed code.

extern char * strndup(const char *, size_t);

I would like to clarify one thing, with small program I don't get effect of stack corruption. It is consistently appearing in my product which has huge amount of function calls.

Using strndup in the following way solved the problem:

dst_str = strndup(src_str, srtlen(src_str));

Please note: used strlen instead of sizeof as i need only the valid string.
I am trying to understand why it is happening.

Behavior i am seeing with my product when i use strndup with large size:

  1. At the "exit" of main, execution is coring with "illegal instruction"
  2. intermittently "Illegal Instruction" in the middle of execution (after strndup call).
  3. Corrupt of some allocated memory, which is no where related to strndup.

All these issues are resolved by just modifying the usage of strndup with actual size of source string.

Thanks & Regards,
Thumbeti

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文