sscanf 导致地址越界
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sscanf 导致地址越界相关的知识,希望对你有一定的参考价值。
问题
test.c
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char *argv[])
int a = 100;
uint8_t b;
sscanf("0x15", "0x%x", &b);
printf("a = 0x%x\\n", a);
printf("b = 0x%x\\n", b);
return EXIT_SUCCESS;
$ ./test.out
a = 0x0
b = 0x15
a 的值为什么变成 0 了呢?
解答
因为 sscanf 在给 b 赋值时,由于指定的参数格式是 %x
,所以 sscanf 认为 b 是一个 unsigned int 类型,所以把 &b 转换成了 unsigned int * 类型,这样在给 b 赋值时,就是按照 unsigned int 这么大空间进行赋值,结果就操作了别的变量的内存,导致程序出问题。
下图 a) 是我们期望的样子,可是由于 “%x”,导致 &b “管控”的空间从一个字节扩大到了四个字节,“侵占”了变量 a 的空间,如图 b),导致 a 的值被篡改。
避免
其实在编译时,编译器就已经发出了警告。所以我们在编写代码时,要时刻留意编译器报的警告,能够帮助我们纠正不少失误。
因此,提交代码的一个原则就是:尽量不引入新的警告。
$ gcc test.c -o test.out
test.c: In function ‘main’:
test.c:10:21: warning: format ‘%x’ expects argument of type ‘unsigned int *’, but argument 3 has type ‘uint8_t *’ aka ‘unsigned char *’ [-Wformat=]
10 | sscanf("0x15", "0x%x", &b);
| ~^ ~~
| | |
| | uint8_t * aka unsigned char *
| unsigned int *
| %hhx
推荐写法
方法一:使用"%hhx"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char *argv[])
int a = 100;
uint8_t b;
sscanf("0x15", "0x%hhx", &b);
printf("a = 0x%x\\n", a);
printf("b = 0x%x\\n", b);
return EXIT_SUCCESS;
$ ./test.out
a = 0x64
b = 0x15
方法二:使用 int 类型中间变量进行转储。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char *argv[])
int a = 100;
uint8_t b;
int c;
sscanf("0x15", "0x%x", &c);
b = (uint8_t)c;
printf("a = 0x%x\\n", a);
printf("b = 0x%x\\n", b);
return EXIT_SUCCESS;
$ ./test.out
a = 0x64
b = 0x15
以上是关于sscanf 导致地址越界的主要内容,如果未能解决你的问题,请参考以下文章