gcc整数溢出检测 __mulvsi3 __addvdi3

gcc整数溢出检测 __mulvsi3 __addvdi3

  • __mulvsi3:乘法结果溢出
  • __addvdi3:加法结果溢出

问题现象

core调用栈有__mulvsi3 或 __addvdi3

Program received signal SIGABRT, Aborted.
0x00110416 in __kernel_vsyscall ()
(gdb) bt
#0 0x00110416 in __kernel_vsyscall ()
#1 0x00555460 in raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2 0x00556e28 in abort () at abort.c:88
#3 0x08048603 in __mulvsi3 ()
#4 0x080484cd in my_atoi (s=0x804870c "7") at main.c:12
#5 0x08048555 in main () at main.c:22
(gdb)

问题原因

在编译时加上 -ftrapv 参数 , 运行时检测到溢出后 , 会产生SIGABRT , 进程终止。
-ftrapv 参数会让GCC在生成代码时,对算数运算结果做溢出检测,如果检测到溢出,则自动abort退出程序。

示例

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

int main(int n, char* args[])
{
    long a = atol(args[1]);
    long b = atol(args[2]);
    long result = a + b;
    printf("result: %d\n", result);
    return 0;
}

编译 gcc -g main.c -ftrapv -o main
执行 ./main 4611686018427387904 4611686018427387904,4611686018427387904是个第63位为1的64位数

[root@localhost ~]# ./main 4611686018427387904 4611686018427387904
Aborted (core dumped)

gdb查看原因

[root@localhost ~]#  gdb main
Reading symbols from main...done.
(gdb) r 4611686018427387904 4611686018427387904
Starting program: /root/main 4611686018427387904 4611686018427387904
Missing separate debuginfos, use: yum debuginfo-install glibc-2.28-164.el8.x86_64
Program received signal SIGABRT, Aborted.
0x00007ffff7a4237f in raise () from /lib64/libc.so.6
(gdb) bt
 0  0x00007ffff7a4237f in raise () from /lib64/libc.so.6
 1  0x00007ffff7a2cdb5 in abort () from /lib64/libc.so.6
 2  0x0000000000400535 in __addvdi3.cold.0 ()
 3  0x0000000000400670 in main (n=3, args=0x7fffffffe3a8) at main.c:8
(gdb) disassemble main      # 查看main函数汇编代码,注意__addvdi3
Dump of assembler code for function main:
   0x0000000000400626 <+0>:     push   %rbp
   0x0000000000400627 <+1>:     mov    %rsp,%rbp
   0x000000000040062a <+4>:     sub    $0x30,%rsp
   0x000000000040062e <+8>:     mov    %edi,-0x24(%rbp)
   0x0000000000400631 <+11>:    mov    %rsi,-0x30(%rbp)
   0x0000000000400635 <+15>:    mov    -0x30(%rbp),%rax
   0x0000000000400639 <+19>:    add    $0x8,%rax
   0x000000000040063d <+23>:    mov    (%rax),%rax
   0x0000000000400640 <+26>:    mov    %rax,%rdi
   0x0000000000400643 <+29>:    callq  0x400520 <atol@plt>
   0x0000000000400648 <+34>:    mov    %rax,-0x8(%rbp)
   0x000000000040064c <+38>:    mov    -0x30(%rbp),%rax
   0x0000000000400650 <+42>:    add    $0x10,%rax
   0x0000000000400654 <+46>:    mov    (%rax),%rax
   0x0000000000400657 <+49>:    mov    %rax,%rdi
   0x000000000040065a <+52>:    callq  0x400520 <atol@plt>
   0x000000000040065f <+57>:    mov    %rax,-0x10(%rbp)
   0x0000000000400663 <+61>:    mov    -0x10(%rbp),%rsi
   0x0000000000400667 <+65>:    mov    -0x8(%rbp),%rdi
   0x000000000040066b <+69>:    callq  0x4006a0 <__addvdi3> # 这里并不是直接使用x86的加法指令,而是调用c库封装的加法函数
   0x0000000000400670 <+74>:    mov    %rax,-0x18(%rbp)
   0x0000000000400674 <+78>:    mov    -0x18(%rbp),%rax
   0x0000000000400678 <+82>:    mov    %rax,%rsi
   0x000000000040067b <+85>:    mov    $0x400798,%edi
   0x0000000000400680 <+90>:    mov    $0x0,%eax
   0x0000000000400685 <+95>:    callq  0x400510 <printf@plt>
   0x000000000040068a <+100>:   mov    $0x0,%eax
   0x000000000040068f <+105>:   leaveq
   0x0000000000400690 <+106>:   retq
End of assembler dump.
(gdb) disassemble __addvdi3     # 进一步查看__addvdi3的汇编
Dump of assembler code for function __addvdi3:
   0x00000000004006a0 <+0>:     endbr64
   0x00000000004006a4 <+4>:     sub    $0x8,%rsp
   0x00000000004006a8 <+8>:     lea    (%rdi,%rsi,1),%rax # 计算a + b的值,结果存在%rax。
   0x00000000004006ac <+12>:    test   %rsi,%rsi
   0x00000000004006af <+15>:    js     0x4006c8 <__addvdi3+40>
   0x00000000004006b1 <+17>:    cmp    %rax,%rdi        # 比较结果与a的值
   0x00000000004006b4 <+20>:    setg   %dl
   0x00000000004006b7 <+23>:    test   %dl,%dl          
   0x00000000004006b9 <+25>:    jne    0x400530 <__addvdi3.cold.0>  # 如果结果比a小(溢出),就跳转到__addvdi3.cold.0,它最终会调用abort
   0x00000000004006bf <+31>:    add    $0x8,%rsp    
   0x00000000004006c3 <+35>:    retq
   0x00000000004006c4 <+36>:    nopl   0x0(%rax)
   0x00000000004006c8 <+40>:    cmp    %rax,%rdi
   0x00000000004006cb <+43>:    setl   %dl
   0x00000000004006ce <+46>:    jmp    0x4006b7 <__addvdi3+23>
End of assembler dump.
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值