美文网首页C语言
C语言-编程中的主要陷阱来源

C语言-编程中的主要陷阱来源

作者: 程序猿编码 | 来源:发表于2020-04-25 20:24 被阅读0次

C 中大多数缓冲区溢出问题可以直接追溯到标准 C 库。最有害的罪魁祸首是不进行自变量检查的、有问题的字符串操作(strcpy、strcat、sprintf 和 gets)。

如果说之前所提到的一些问题可能只是影响部分功能的实现,那么缓冲区溢出将可能会造成程序运行终止,被不安全代码攻击等严重问题,因此我们不得不特别重视。

本专栏文章的主题是,通过防御性编程保护代码不受缓冲区溢出攻击。

永远不要使用 gets()

#include <stdio.h>

int main(int argc, char **argv){

    char buf[128];
    gets(buf);

}

编译:

编译时编译器会检查不建议使用"gets"。该函数从标准输入读入用户输入的一行文本,它在遇到 EOF 字符或换行字符之前,不会停止读入文本。也就是:gets() 根本不执行边界检查。因此,使用 gets() 总是有可能使任何缓冲区溢出。

可以将程序改为:

#include <stdio.h>

#define BUFSIZE 128

int main(int argc, char **argv){

    char buf[BUFSIZE];
    fgets(buf,BUFSIZE,stdin);

}

编译运行:

作为一个替代方法,可以使用方法 fgets()。它可以做与 gets() 所做的同样的事情,但它接受用来限制读入字符数目的大小参数,因此,提供了一种防止缓冲区溢出的方法。

C 编程中的主要陷阱

库函数中还有一些函数也可能造成缓冲区溢出,我们应该尽量避免使用它们。

strcpy()
strcat()
sprintf()
scanf()
sscanf()
fscanf()
vfscanf()
vsprintf
vscanf()
vsscanf()

如果有任何可能,避免使用这些函数。在大多数情况下,都有合理的替代方法。我们将仔细检查它们中的每一个,所以可以看到什么构成了它们的误用,以及如何避免它。

strcpy()函数将源字符串复制到缓冲区。没有指定要复制字符的具体数目。复制字符的数目直接取决于源字符串中的数目。如果源字符串碰巧来自用户输入,且没有专门限制其大小,则有可能会陷入大的麻烦中!

如果知道目的地缓冲区的大小,则可以添加明确的检查:

if(strlen(src) >= dst_size) {

  ...

  }else {

  strcpy(dst, src);
}

或者使用strncpy() 库函数:

strncpy(dst, src, dst_size-1);
  dst[dst_size-1] = '\0'; /* 这样做是为了安全!*/

如果 src 比 dst 大,则该函数不会抛出一个错误;当达到最大尺寸时,它只是停止复制字符。注意上面调用 strncpy() 中的 dst_size-1。如果 src 比 dst 长,则那给我们留有空间,将一个空字符放在 dst 数组的末尾。

确保 strcpy() 不会溢出的另一种方式是,在需要它时就分配空间,确保通过在源字符串上调用 strlen() 来分配足够的空间:

dst = (char *)malloc(strlen(src));
  strcpy(dst, src);

strcat()函数非常类似于 strcpy(),除了它可以将一个字符串合并到缓冲区末尾。它也有一个类似的、更安全的替代方法 strncat()。如果可能,使用 strncat() 而不要使用 strcat()。

使用 sprintf() 和 vsprintf() 与使用 strcpy() 一样,都很容易对程序造成缓冲区溢出。

继续, scanf系列的函数也设计得很差。在这种情况下,目的地缓冲区会发生溢出。考虑以下代码:

#include <stdio.h>

int main(int argc, char **argv){

  char buf[256];
  sscanf(argv[0], "%s", &buf);

  //sscanf(argv[0], "%255s", &buf);

}

如果输入的字大于 buf 的大小,则有溢出的情况。幸运的是,有一种简便的方法可以解决这个问题。考虑以下代码,它没有安全性方面的薄弱环节。

就是在百分号和 s 之间的 255 指定了实际存储在变量 buf 中来自 argv[0] 的字符不会超过 255 个。其余匹配的字符将不会被复制。

总结

缓冲区溢出造成的危害非常大,可能导致程序运行终止或程序运行异常且难以定位问题。

"缓冲区溢出"漏洞是一个由来已久的漏洞类型,虽然现代操作系统的编译器,已经可以很大程度的阻止此类型漏洞的出现,但是作为一名C/C++程序员,还是有必要对此类漏洞的原理进行一定了解哈。

所以缓冲区溢出的原理非常简单,总结起来就是一句话:程序向缓冲区写入了超过缓冲区最大能保存的数据。

程序猿编码

欢迎关注公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下:

相关文章

  • C语言-编程中的主要陷阱来源

    C 中大多数缓冲区溢出问题可以直接追溯到标准 C 库。最有害的罪魁祸首是不进行自变量检查的、有问题的字符串操作(s...

  • Category原理解析

    前言 在 iOS 开发中,使用的编程语言主要是 Objective-C。这一种编程语言虽然是 C/C++ 的扩展,...

  • 书籍推荐

    1.《C primer plus》----《C程序设计语言》-----《C和指针》、《C专家编程》、《C缺陷与陷阱...

  • BIM开发会用到哪些技术

    1. 编程语言 常用的编程语言,其中以C#为主。C#语言是Windows平台下的旗舰级开发语言,BIM应用程序主要...

  • python动态添加属性

    动态编程语言是高级语言设计的一中类型,常见的动态编程语言javascript/php/Ruby,而C/c++/C#...

  • 物联网开发必备C语言技巧

    在物联网开发中,C语言基础性错误的不断发生,会导致某些缺陷的产生并造成维护方面的困扰。为竭力避免这些C编程陷阱,这...

  • C语言中的指针和内存泄漏,不是小问题!

    C语言作为编程的入门语言,他在编程中地位可想而知。 对于任何使用 C 语言的人,如果问他们 C 语言的最大烦恼是什...

  • C++编译器无法捕捉到的8种错误

    前言 C++是一种复杂的编程语言,其中充满了各种微妙的陷阱。在C++中几乎有数不清的方式能把事情搞砸。幸运的是,如...

  • 学炫彩夺目C语言图形编程,开C语言另一扇窗,写有意思代码

    本文内容主要是源码分享(炫彩夺目的C语言图形编程,打开C语言学习一扇窗,丰富编程人生视频源码)更多有意思C语言图形...

  • CUDA编程概述

    CUDA C 的编程接口主要包括一个对C语言的小扩展集以及一个runtime库。 核心的语言扩展在于编程模型,就是...

网友评论

    本文标题:C语言-编程中的主要陷阱来源

    本文链接:https://www.haomeiwen.com/subject/ccqlwhtx.html