时尚

漏洞struct

字号+ 作者:烟消火灭网 来源:娱乐 2026-10-17 09:01:00 我要评论(0)

我翻过一套老旧的C代码,里面有个结构体,定义得规规矩矩,字段排列整齐,注释也写得勤快。可就是这套代码,在某个凌晨三点,让整个服务崩了十分钟。问题不在逻辑,在struct本身——它有个洞,一个看不见的洞

我翻过一套老旧的漏洞C代码,里面有个结构体,漏洞定义得规规矩矩,漏洞字段排列整齐,漏洞注释也写得勤快。漏洞可就是漏洞这套代码,在某个凌晨三点,漏洞让整个服务崩了十分钟。漏洞问题不在逻辑,漏洞在struct本身——它有个洞,漏洞一个看不见的漏洞洞。

那个洞叫内存对齐。漏洞你写struct { char a; int b; },漏洞编译器不会老老实实把a放在偏移0、漏洞b放在偏移1。漏洞它会悄悄在a后面塞三个填充字节,让b对齐到4字节边界。这本来是为了CPU访问效率,可如果你把这个结构体直接write到文件里,或者通过socket发给另一台机器,那三个填充字节就成了不确定的垃圾。你以为是固定长度的协议,结果每个包都带着随机杂质。对面解析的时候,校验和永远对不上。

更阴险的是另一种洞——位域。程序员喜欢用位域来节省空间,把几个标志位塞进一个int里。看着很美,可位域的布局是implementation-defined。GCC和MSVC的排列顺序可能正好相反。你在一台机器上序列化的数据,换台机器读出来,所有标志位全部错位,像把汉字按拼音排序后发给一个按笔画查字典的人。

我自己踩过最深的坑,是结构体里的柔性数组。C99允许你写struct { int len; char data[]; },这个data不占空间,只是个占位符。我那时候年轻,以为malloc一个sizeof(struct) + len就万事大吉。结果忘了结构体本身有对齐要求,malloc出来的内存,data的起始地址可能不是对齐的。在某些架构上,访问未对齐的int指针,直接SIGBUS,进程当场暴毙。不是崩溃,是直接被操作系统拍死。

你以为这些问题只在C里?C++的struct继承了所有C的毛病,还多加了构造函数、析构函数、虚函数表指针。你memcpy一个带虚函数的对象,等于把vptr也复制了一份。如果源对象和目的对象的类型不完全一致,那个vptr可能指向一个错误的方法表。调用虚函数的时候,程序跳到一个莫名其妙的地址,然后——段错误。你查半天,发现不过是把一个struct赋值给了另一个类型相似的struct。

这些洞从来不会被编译器警告。它们藏在类型系统的缝隙里,只有当你把内存当作字节流来搬运时才会露头。现代语言里,Go的struct有明确的对齐规则,Rust干脆用repr(C)来显式控制布局,Python的__slots__也避免了字典的开销。可那些老代码还在跑,在银行、在飞机、在心脏起搏器里。它们的struct上依然开着洞,只是没人再去碰那个凌晨三点的文件了。

所以,每当你看到一个struct定义,别只盯着字段名。想想它背后有多少看不见的填充字节,多少未定义的布局规则,多少靠编译器心情决定的排列顺序。那是一个个沉默的陷阱,等着某个信任它的程序员一脚踩空。

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 只有通过身份认证的人才允许上公司内网

    只有通过身份认证的人才允许上公司内网

    2026-10-17 08:35

  • scanport端口扫描修复漏洞

    scanport端口扫描修复漏洞

    2026-10-17 08:27

  • 电脑弹出什么境外传输

    电脑弹出什么境外传输

    2026-10-17 07:51

  • 安阳高铁站客服电话

    安阳高铁站客服电话

    2026-10-17 06:48

网友点评