You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

statfs调用触发栈缓冲区溢出问题排查及原因确认

statfs栈缓冲区溢出问题排查与疑问

运行时错误日志

==33949==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x000103d3d970 at pc 0x00010172b930 bp 0x00016fdfeed0 sp 0x00016fdfe688
WRITE of size 2168 at 0x000103d3d970 thread T0
    #0 0x10172b92c in wrap_statfs+0x2ac (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x2b92c)
    #1 0x107a10ccc in StatFsErr() OtherFile.c:546
    #2 0x1000c3318 in main main.cpp:141
    #3 0x193d43f24  (<unknown module>)

Address 0x000103d3d970 is located in stack of thread T0 at offset 368 in frame
    #0 0x107a10a64 in StatFsErr() OtherFile.c:538

  This frame has 2 object(s):
    [32, 368) 'sb' (line 541)
    [432, 1457) 'path' (line 542) <== Memory access at offset 368 partially underflows this variable

原始代码实现

OtherFile.c

void StatFsErr()
{
  struct statfs sb;
  char path[PATH_MAX + 1];
  memset(path, 0, sizeof(path));
  path[0] = '/';
  OSStatus    err = statfs(path, &sb);
}

main.cpp

#include "OtherFile.h"
int main(int argc, char **argv)
{
  StatFsErr();
  return 0;
}

异常差异现象

将StatFsErr()内的代码直接移到main()中执行时,不会触发错误:

int main(int argc, char **argv)
{
  struct statfs sb;
  char path[PATH_MAX + 1];
  memset(path, 0, sizeof(path));
  path[0] = '/';
  OSStatus    err = statfs(path, &sb);
  return 0;
}

我原本推测是栈溢出,但无法理解statfs为何会执行如此大的写入操作。根据Linux的statfs文档,它仅会将路径对应的文件系统信息写入sb,而struct statfs本身应该能正常存放在栈中。

临时解决方法

以下写法可以规避错误,但无法解释根本原因:

char sb_buf [2200];
char path[PATH_MAX + 1];
memset(path, 0, sizeof(path));
path[0] = '/';
OSStatus    err = statfs(path, (struct statfs *)sb_buf);

问题定位更新

根据提示,发现问题是编译OtherFile.c时使用了-D__DARWIN_64_BIT_INO_T=0选项导致。最小复现示例如下:

最小复现代码(main.cpp)

int main(int argc, char **argv)
{
  struct statfs sb;
  char path[PATH_MAX + 1] = "/";
  OSStatus    err = statfs(path, &sb);
  return 0;
}

使用-D__DARWIN_64_BIT_INO_T=0编译该代码会触发相同错误:

=================================================================
==36752==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x000103cb1170 at pc 0x00010169f930 bp 0x00016fdff0b0 sp 0x00016fdfe868
WRITE of size 2168 at 0x000103cb1170 thread T0
    #0 0x10169f92c in wrap_statfs+0x2ac (libclang_rt.asan_osx_dynamic.dylib:arm64e+0x2b92c)
    #1 0x1000bc880 in main main.cpp:11
    #2 0x193d43f24  (<unknown module>)

Address 0x000103cb1170 is located in stack of thread T0 at offset 368 in frame
    #0 0x1000bc604 in main main.cpp:5

  This frame has 2 object(s):
    [32, 368) 'sb' (line 7)
    [432, 1457) 'path' (line 8) <== Memory access at offset 368 partially underflows this variable

我的推测是:由于APFS使用64位inode,macOS内核会返回mount.h中定义的2168字节大小的64位struct statfs结构体,而编译选项-D__DARWIN_64_BIT_INO_T=0让代码中生成的是32位inode版本的struct statfs(尺寸更小),从而导致内核写入时超出缓冲区大小,触发栈溢出。

请问该推测是否正确?


内容的提问来源于stack exchange,提问作者AbsoluteBeginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:04:57