c语言攻击编码,C语言安全编码(1)

编码规范的目的:

保证不同背景和经历的开发人员可以良好的协同开发

保证组织级的开发技能和经验得以共享和传承

后面我会逐步分享这段时间学习的安全编码规范。

1.对象的持续期

每个对象都有一个生命周期,如果一个对象在生命周期外被引用,则该行为是未定义的,当生命周期结束时,指针值就变的不确定了。

(1)例1.1:不同的生命周期

1// 例1.1

2char *p;

3void func()

4{

5  char str[] = "abcdefg";

6  p = str;    // error

7}

8

9int main()

10{

11  func();

12  printf("%s\n",p)

13  return 0;

14}

在这段代码中,str的

生命周期仅在func函数执行期内,当func函数运行结束时,str就失效了,但p中还存储了str的地址。

对于上面的情况,合适的处理方法如下:

1// 例1

2// p和str的持续时间是一致的

3void func()

4{

5  char str[] = "abcdefg";

6  char *p = str;

7}

或者 :

1// 在str被销毁之前设置p为NULL,防止p取不确定值

2char *p;

3void func()

4{

5  char str[] = "abcdefg";

6  p = str;    // error

7  /*...*/

8  p = NULL;

9}

(2)例1.2:返回值

1// 例1.2

2char* func()

3{

4  char arr[5];

5  /*.....*/

6  return arr;

7}

在这段代码中,arr的

生命周期仅在func函数执行期内,当函数返回时,arr变量已经释放,编译器会产生警告。

对于上面的情况,合适的处理方法如下:

1// 需要修改arr的值,应该以地址的方式传递给函数

2// 这样才能让arr在函数外得以保持

3void func(char* arr, size_t len)

4{

5  /*......*/

6  return;

7}

(3)例1.3:输出参数

1// 例1.3

2void fun1(char **ptr)

3{

4  char arr[10];

5  /*...*/

6  *ptr = arr;

7}

8

9void fun2()

10{

11  char *p;

12  func1(&p);

13}

在这段代码中,fun1存储了一个本地数组arr,并将函数参数指针ptr指向arr,当fun1返回后,ptr指向的变量已经释放。

对于上面的情况,合适的处理方法如下:

1// 将变量arr定义为全局变量

2char arr[10];

3void fun1(char **ptr)

4{

5  /*...*/

6  *ptr = arr;

7}

8

9void fun2()

10{

11  char *p;

12  func1(&p);

13}

2.禁止访问未初始化的内存

局部变量在未初始化就使用,变量值是未定的,访问这个变量将产生不可预料的后果。某些分配动态内存的函数调用时将不会对分配的内存进行初始化,例如malloc()、aligned_alloc()、realloc()等。

(1)例2.1:Return by Reference

1//例2.1

2void func(int n, int *p)

3{

4  if(p == NULL) {

5    return;

6  }

7

8  if(n > 0) {

9    *p = 1;

10  }

11  else if(n 

12    *p = 2;

13  }

14}

15

16int call(int num)

17{

18  int flag;

19  func(num, flag);

20  return num;

21}

这段代码中,原本的意图是根据num的值来改变flag的值,但忽略了num为0的情况,在实际运行时,若num=0,则flag未被初始化,可能导致不可预料的后果。

对于上面的情况,合适的处理方法如下:

1void func(int n, int *p)

2{

3  if(p == NULL) {

4    return;

5  }

6

7  if(n >= 0) {  // 增加等于0的情况

8    *p = 1;

9  }

10  else if(n 

11    *p = 2;

12  }

13}

(2)例2.2:uninitialized local

1//例2.2

2#define BUF_SIZE 24

3void myprint(char *msg)

4{

5  const char *log = msg;

6  char buf[BUF_SIZE];

7

8  sprintf(buf,"%s\n", log);

9  printf("%s\n", buf);

10}

这段代码中,如果msg引用的字符串超过了17个字节,则会发生缓冲区溢出。

对于上面的情况,合适的处理方法如下:

1#define BUF_SIZE 24

2void myprint(char *msg)

3{

4  char buf[BUF_SIZE];

5

6  // 调用snprintf()消除缓存区溢出

7  if(0 

8    printf("%s\n", buf);

9  }

10  else {

11    printf("ERROR\n");

12  }

13}

(3)例2.3:mbstate_t初始化

1//例2.3

2#include 

3#include 

4

5void func(char *msg)

6{

7  size_t len;

8  mbstste_t state;

9  len = mbrlen(msg, strlen(msg), &state);

10}

对于上面的情况,合适的处理方法如下:

1void func(char *msg)

2{

3  size_t len;

4  mbstste_t state;

5  memset(&state, 0, sizeof(state)); // 将mbstate_t对象初始化为0

6  len = mbrlen(msg, strlen(msg), &state);

7}

(4)例2.4:realloc()函数

1#define OLDSIZE 10

2#define NEWSIZE 20

3int func_array(int *arr, int count)

4{

5  if(count == 0) {

6    return 0;

7  }

8  int *res = (int *)realloc(arr, count * sizeof(int));

9  if(res == NULL) {

10    free(res);

11    return 0;

12  }

13  return res;

14}

15

16void func()

17{

18  int *array = (int *)malloc(OLDSIZE * sizeof(int));

19  if(array == NULL) {

20    /* error */

21  }

22

23  for(int i = 0; i 

24    array[i]=i + 1;

25  }

26

27  array = func_array(array, NEWSIZE);

28  if(array == NULL) {

29    /* error */

30  }

31

32  for(int i = 0; i 

33    printf("%d ",array[i]);

34  }

35}

这段代码中,realloc()函数改变动态分配的内存的大小,返回内存对象最初的size个字节没有变化,但新添加空间没有初始化,其值不确定。

对于上面的情况,合适的处理方法如下:

1#define OLDSIZE 10

2#define NEWSIZE 20

3// 第二个参数作为旧的长度

4int func_array(int *arr, int oldcount, int newcount)

5{

6  if(newcount == 0) {

7    return 0;

8  }

9  int *res = (int *)realloc(arr, newcount * sizeof(int));

10  if(res == NULL) {

11    free(res);

12    return 0;

13  }

14

15  if(newcount > oldcount) {

16    memset(res + oldcount, 0, (newcount - oldcount) * sizeof(int));

17  }

18

19  return res;

20}

3

.禁止对NULL指针解引用

对NULL指针解引用是未定义行为,可能导致程序异常终止。

(1)例3.1

1void func(char *str)

2{

3  int len = strlen(str) + 1;

4  char *c_str = (char *)malloc(len);

5  memcpy(c_str, str, len);

6  /*...*/

7}

这段代码中,str拷贝给c_str指向的动态分配内存,但如果malloc()失败,c_str=NULL,此时运行memcpy会出现未定义行为。

对于上面的情况,合适的处理方法如下:

1void func(char *str)

2{

3  if(str == NULL) {  // 确保str指针不是NULL

4    /* error */

5  }

6

7  int len = strlen(str) + 1;

8  char *c_str = (char *)malloc(len);

9  if(c_str == NULL) {    // 确保malloc返回值不是NULL

10    /* error */

11  }

12

13  memcpy(c_str, str, len);

14  /*...*/

15}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值