当前位置: 首页 > news >正文

81 柔性数组造成的一些奇怪情况

前言

测试用例是来自于 陈皓 老师的博客

C语言结构体里的成员数组和指针

主要是测试 结构体中柔性数组 的相关特性

然后 参照的对象是 和 结构体中指针 来作为参照

然后 可以看到一些奇怪的现象, 然后 一去调试 发现更加奇怪

 

 

测试用例

#include "stdio.h"struct str {int len;char s[0];
//    char *s;
};struct foo {struct str *a;
};int main() {struct foo f = {0};if (f.a->s) {printf(" this is in if scope \n");printf(" printf %s \n", f.a->s);}return 0;
}

 

 

然后执行程序, 效果如下, 然后 有点意外的是 居然进了 if block  

root@ubuntu:~/Desktop/linux/HelloWorld# ./Test19AccessArray0this is in if scope
Segmentation fault

 

 

来调试看一下 情况, 这里 f.a 为 NULL, 然后 居然没有报错? 

 

然后 会产生一个 SIGSEGV 的信号 

 

 

柔性数组成员编译之后的 main 

上下文的信息如下

可以看到的是这里 获取到 f.a 为 0, 然后 f.a->s 是 0 + 4[s的偏移]

然后 因此 得到的是上面的一系列的情况

最终 SIGSEGV 是在 printf 里面, 访问地址4, 然后 是一个非法的地址, 内核发送了 SIGSEGV 信号量 

(gdb) list 17
12      };
13
14      int main() {
15
16          struct foo f = {0};
17          if (f.a->s) {
18              printf(" this is in if scope \n");
19              printf(" printf %s \n", f.a->s);
20          }
21
(gdb) b Test19AccessArray0.c:17
Breakpoint 1 at 0x400576: file Test19AccessArray0.c, line 17.
(gdb) run
Starting program: /root/Desktop/linux/HelloWorld/Test19AccessArray0Breakpoint 1, main () at Test19AccessArray0.c:17
17          if (f.a->s) {
(gdb) disassemble
Dump of assembler code for function main:0x0000000000400566 <+0>:     push   %rbp0x0000000000400567 <+1>:     mov    %rsp,%rbp0x000000000040056a <+4>:     sub    $0x10,%rsp0x000000000040056e <+8>:     movq   $0x0,-0x10(%rbp)
=> 0x0000000000400576 <+16>:    mov    -0x10(%rbp),%rax0x000000000040057a <+20>:    add    $0x4,%rax0x000000000040057e <+24>:    test   %rax,%rax0x0000000000400581 <+27>:    je     0x4005a7 <main+65>0x0000000000400583 <+29>:    mov    $0x400634,%edi0x0000000000400588 <+34>:    call   0x400430 <puts@plt>0x000000000040058d <+39>:    mov    -0x10(%rbp),%rax0x0000000000400591 <+43>:    add    $0x4,%rax0x0000000000400595 <+47>:    mov    %rax,%rsi0x0000000000400598 <+50>:    mov    $0x40064a,%edi0x000000000040059d <+55>:    mov    $0x0,%eax0x00000000004005a2 <+60>:    call   0x400440 <printf@plt>0x00000000004005a7 <+65>:    mov    $0x0,%eax0x00000000004005ac <+70>:    leave0x00000000004005ad <+71>:    ret
End of assembler dump.
(gdb) nexti
0x000000000040057a      17          if (f.a->s) {
(gdb) info registers
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x7fffffffe588      140737488348552
rsi            0x7fffffffe578      140737488348536
rdi            0x1                 1
rbp            0x7fffffffe490      0x7fffffffe490
rsp            0x7fffffffe480      0x7fffffffe480
r8             0x400620            4195872
r9             0x7ffff7de7af0      140737351940848
r10            0x846               2118
r11            0x7ffff7a2d750      140737348032336
r12            0x400470            4195440
r13            0x7fffffffe570      140737488348528
r14            0x0                 0
r15            0x0                 0
rip            0x40057a            0x40057a <main+20>
eflags         0x202               [ IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) nexti
0x000000000040057e      17          if (f.a->s) {
(gdb) info registers
rax            0x4                 4
rbx            0x0                 0
rcx            0x0                 0
rdx            0x7fffffffe588      140737488348552
rsi            0x7fffffffe578      140737488348536
rdi            0x1                 1
rbp            0x7fffffffe490      0x7fffffffe490
rsp            0x7fffffffe480      0x7fffffffe480
r8             0x400620            4195872
r9             0x7ffff7de7af0      140737351940848
r10            0x846               2118
r11            0x7ffff7a2d750      140737348032336
r12            0x400470            4195440
r13            0x7fffffffe570      140737488348528
r14            0x0                 0
r15            0x0                 0
rip            0x40057e            0x40057e <main+24>
eflags         0x202               [ IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

 

 

指针成员编译之后的 main 

将结构体 str 中的 s 成员更新成为 “char *s”

然后 再来看一下 具体的效果

这下可以看到的是 在访问 f.a->s 的时候 就已经出现了异常

 

 

可以看到的是这里 获取到 f.a 为 0, 然后 f.a->s 是 访问 0 的数据

然后 访问地址0, 然后 是一个非法的地址, 内核发送了 SIGSEGV 信号量 

(gdb) list 17
12      };
13
14      int main() {
15
16          struct foo f = {0};
17          if (f.a->s) {
18              printf(" this is in if scope \n");
19              printf(" printf %s \n", f.a->s);
20          }
21
(gdb) b Test19AccessArray0.c:17
Breakpoint 1 at 0x400576: file Test19AccessArray0.c, line 17.
(gdb) run
Starting program: /root/Desktop/linux/HelloWorld/Test19AccessArray0Breakpoint 1, main () at Test19AccessArray0.c:17
17          if (f.a->s) {
(gdb) disassemble
Dump of assembler code for function main:0x0000000000400566 <+0>:     push   %rbp0x0000000000400567 <+1>:     mov    %rsp,%rbp0x000000000040056a <+4>:     sub    $0x10,%rsp0x000000000040056e <+8>:     movq   $0x0,-0x10(%rbp)
=> 0x0000000000400576 <+16>:    mov    -0x10(%rbp),%rax0x000000000040057a <+20>:    mov    0x8(%rax),%rax0x000000000040057e <+24>:    test   %rax,%rax0x0000000000400581 <+27>:    je     0x4005a7 <main+65>0x0000000000400583 <+29>:    mov    $0x400634,%edi0x0000000000400588 <+34>:    call   0x400430 <puts@plt>0x000000000040058d <+39>:    mov    -0x10(%rbp),%rax0x0000000000400591 <+43>:    mov    0x8(%rax),%rax0x0000000000400595 <+47>:    mov    %rax,%rsi0x0000000000400598 <+50>:    mov    $0x40064a,%edi0x000000000040059d <+55>:    mov    $0x0,%eax0x00000000004005a2 <+60>:    call   0x400440 <printf@plt>0x00000000004005a7 <+65>:    mov    $0x0,%eax0x00000000004005ac <+70>:    leave0x00000000004005ad <+71>:    ret
End of assembler dump.
(gdb) nexti
0x000000000040057a      17          if (f.a->s) {
(gdb) info registers
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x7fffffffe588      140737488348552
rsi            0x7fffffffe578      140737488348536
rdi            0x1                 1
rbp            0x7fffffffe490      0x7fffffffe490
rsp            0x7fffffffe480      0x7fffffffe480
r8             0x400620            4195872
r9             0x7ffff7de7af0      140737351940848
r10            0x846               2118
r11            0x7ffff7a2d750      140737348032336
r12            0x400470            4195440
r13            0x7fffffffe570      140737488348528
r14            0x0                 0
r15            0x0                 0
rip            0x40057a            0x40057a <main+20>
eflags         0x202               [ IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) nextiProgram received signal SIGSEGV, Segmentation fault.
0x000000000040057a in main () at Test19AccessArray0.c:17

 

 

 

 

 

http://www.xdnf.cn/news/1346077.html

相关文章:

  • 农业-学习记录
  • 关于 WebDriver Manager (自动管理浏览器驱动)
  • 当下一次攻击发生前:微隔离如何守护高敏数据,防范勒索攻击下的数据泄露风险!
  • 一、Python IDLE安装(python官网下的环境安装)
  • 腾讯云EdgeOne安全防护:快速上手,全面抵御Web攻击
  • Datawhale AI夏令营---coze空间共学
  • 【图像算法 - 21】慧眼识虫:基于深度学习与OpenCV的农田害虫智能识别系统
  • 关于日本服务器的三种线路讲解
  • 在自动驾驶中ESKF实现GINS时,是否将重力g作为变量考虑进去的目的是什么?
  • ASPICE过程能力确定——度量框架
  • Unity--判断一个点是否在扇形区域里面(点乘和叉乘的应用)
  • 视觉语言大模型应用开发——基于 CLIP、Gemini 与 Qwen2.5-VL 的视频理解内容审核全流程实现
  • ref 简单讲解
  • flutter geolocator Android国内定位失败问题解决
  • JVM 调优全流程案例:从频繁 Full GC 到百万 QPS 的实战蜕变
  • 【大模型本地运行与部署框架】Ollama的cmd常用命令
  • Linux 软件编程(九)网络编程:IP、端口与 UDP 套接字
  • 【Python】两条命令永久切国内源
  • 本地组策略编辑器图形化工具
  • 力扣(在排序数组中查找元素的第一个和最后一个位置)
  • 当我们想用GPU(nlp模型篇)
  • 开源 python 应用 开发(十)音频压缩
  • 开源 python 应用 开发(十一)短语音转文本
  • ZKmall模块商城的跨境电商支付安全方案:加密与权限的双重防护
  • 数据结构 -- 树
  • STM32G4-比较器
  • 亚马逊老品怎么再次爆发流量?
  • 计算机内存中的整型存储奥秘、大小端字节序及其判断方法
  • 量子计算基础
  • 豆包AI PPT与秒出PPT对比评测:谁更适合你?