C语言入坑指南-缓冲区溢出
前言
缓冲区溢出通常指的是向缓冲区写入了超过缓冲区所能保存的最大数据量的数据。如果说之前所提到的一些问题可能只是影响部分功能的实现,那么缓冲区溢出将可能会造成程序运行终止,被不安全代码攻击等严重问题,因此我们不得不特别重视。
一个缓冲区溢出的例子
对于下面的程序:
#include <stdio.h>
#include <string.h>
int main(void)
{
char buff[8] = {0};
char *p = "0123456789";
strcpy(buff,p);
printf("%s\n",buff);
return 0;
}
定义一个字符数组buff,数组长度为8,使用strcpy函数将p所指向的字符串常量拷贝到buff中。
运行程序,结果如下:
0123456789
*** stack smashing detected ***: ./buff terminated
已放弃 (核心已转储)
可以看到,由于p所指向的字符串长度大于buff的长度,拷贝时由于缓冲区溢出而破坏了栈中的内容而导致程序异常终止。
实际上,有时候缓冲区溢出导致程序马上运行出错是幸运的,因为我们至少能够知道这里出错了。而不幸的情况是,如果超出buff的部分存储在了栈帧不属于它自己的位置,即覆盖了栈帧上存储的其他信息,就有可能导致程序在其他位置出错,造成问题难以定位。
当然也有很幸运的时候,那就是超出buff的部分存储在了未被使用的栈空间上。但是我们绝对不可以对此抱有侥幸心理。
如何避免
对于前面所示的例子中,我们可以很明显地看到要拷贝的字符串长度大于buff的长度,我们可以选择将buff的长度增大。但是实际编程中,我们经常难以察觉是否会超过缓冲区大小。
比如,对于gets函数:
char buff[255];
gets(buff);
我们不会知道用户在控制台会输入多少字符,但是可以肯定的是,输入字符很有可能会超过255,甚至字符中包含了可以执行代码的字节编码(当然,编译器和操作系统有很多机制,例如栈随机化,栈破坏检测,限制可执行代码区域等来对抗缓冲区溢出攻击),这个时候,灾难就会发生了。
因此我们不应该使用像gets这样不安全的函数,而选择fgets这样的可替代函数。查看gets函数的手册发现,手册中甚至直言不讳地说道:Never use gets()。
同样的,库函数中还有一些函数也可能造成缓冲区溢出,我们应该尽量避免使用它们,而选择使用更加安全的版本。
| 作用 | 不推荐使用函数 | 推荐使用函数 |
|---|---|---|
| 拷贝字符串 | strcpy | strncpy |
| 字符串比较 | strcmp | strncmp |
| 字符串连接 | strcat | strncat |
| 格式化字符串并存入缓冲区 | sprintf | snprintf |
| 读取字符串 | gets | fgets |
| 复制字符串 | strdup | strndup |
| 字符串比较忽略大小写 | strcasecmp | strncasecmp |
其中推荐使用的函数特点是,限定了操作内容的大小,从而避免了缓冲区溢出。当然,可能也会带来另外一个问题,就是截断。
我们修改一下前面的程序:
#include <stdio.h>
#include <string.h>
int main(void)
{
char buff[8] = {0};
char *p = "01234567890123";
strncpy(buff,p,sizeof(buff));
printf("%s\n",buff);
return 0;
}
运行结果如下:
01234567
可以看到,虽然部分字符串没有被拷贝,但是避免了缓冲区溢出,程序不再异常终止。
总结
缓冲区溢出造成的危害非常大,可能导致程序运行终止或程序运行异常且难以定位问题。当然有时候,也能够正常运行,但我们不能够抱有侥幸心理。因此在实际编程中,尽量选择那些更加安全的函数来避免缓冲区溢出。而有些时候并不一定有更加安全的函数可替代,这种时候,我们需要自己特别关注。
C语言入坑指南-缓冲区溢出的更多相关文章
- C语言入坑指南-被遗忘的初始化
前言 什么是初始化?为什么要初始化?静态变量和局部变量的初始化又有什么区别?实际应用中应该怎么做?本文将一一回答这些问题. 什么是初始化 初始化指的是对数据对象或者变量赋予初始值.例如: int va ...
- C语言入坑指南-数组之谜
前言 在C语言中,数组和指针似乎总是"暧昧不清",有时候很容易把它们混淆.本文就来理一理数组和指针之间到底有哪些异同. 数组回顾 在分析之前,我们不妨回顾一下数组的知识.数组是可以 ...
- ElasticSearch入坑指南之概述及安装
---恢复内容开始--- ElasticSearch入坑指南之概述及安装 了解ElasticSearch ElasticSearch(简称ES)基于Lucene的分布式全文检索引擎.使用ES可以实现近 ...
- Rust入坑指南:核心概念
如果说前面的坑我们一直在用小铲子挖的话,那么今天的坑就是用挖掘机挖的. 今天要介绍的是Rust的一个核心概念:Ownership.全文将分为什么是Ownership以及Ownership的传递类型两部 ...
- Rust入坑指南:鳞次栉比
很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉比"这个标题是不是显得很有文化? 在Rust入坑指南:常规套路一文中我们已经介绍 ...
- electron入坑指南
electron入坑指南 简介 electron 实际集成chrome浏览器和node环境, 运行你写的网页 app 基本目录结构 index.html 名称可以不是index, 这个文件与普通网页的 ...
- Elasticsearch入坑指南之RESTful API
Elasticsearch入坑指南之RESTful API Tags:Elasticsearch ES为开发者提供了非常丰富的基于Http协议的Rest API,通过简单的Rest请求,就可以实现非常 ...
- eclipse中导入外部包却无法查看对应源码或Javadoc的入坑指南
eclipse中导入外部包却无法查看对应源码或Javadoc的 入坑指南 出现这个错误的原因是,你虽然导入了.jar包,但没有配置对应的Javadoc或源码路径,所以在编辑器中无法查看源 码和对应AP ...
- Rust入坑指南:亡羊补牢
如果你已经开始学习Rust,相信你已经体会过Rust编译器的强大.它可以帮助你避免程序中的大部分错误,但是编译器也不是万能的,如果程序写的不恰当,还是会发生错误,让程序崩溃.所以今天我们就来聊一聊Ru ...
随机推荐
- linux的fcntl函数
fcntl可实现对指定文件描述符的各种操作,例如获取/设置 文件的是否可以被读写的状态,等其他状态. int fcntl (int __fd, int __cmd, ...);The remainin ...
- 串的两种模式匹配方式(BF/KMP算法)
前言 串,又称作字符串,它是由0个或者多个字符所组成的有限序列,串同样可以采用顺序存储和链式存储两种方式进行存储,在主串中查找定位子串问题(模式匹配)是串中最重要的操作之一,而不同的算法实现有着不同的 ...
- LeetCode 145. 二叉树的后序遍历(Binary Tree Postorder Traversal)
145. 二叉树的后序遍历 145. Binary Tree Postorder Traversal 题目描述 给定一个二叉树,返回它的 后序 遍历. LeetCode145. Binary Tree ...
- 039 Android SQLite数据库(了解)
1.介绍 注意:当有大量相似结构的数据需要存储的时候,需要使用数据库. 2.SQLiteOpenHelper简介 注意:数据库的创建方法总结: (1)定义一个类继承SQLiteOpenHelper o ...
- [转帖]两种以太网 RDMA 协议: iWARP 和 RoCE
两种以太网 RDMA 协议: iWARP 和 RoCE https://weibo.com/p/1001603936363903889917?mod=zwenzhang 写的挺好的呢. 本文是讲演 H ...
- springboot之Redis
1.springboot之Redis配置 在学习springboot配置Redis之前先了解Redis. 1.了解Redis Redis简介: redis是一个key-value存储系统.和Memca ...
- fputcsv 导出excel,解决内存、性能、乱码、科学计数法问题
在PHP的日常开发中,时常会需要导出 excel ,一般我们会使用 PHPExcel ,性能强大,但是在数据量大的时候,phpexcel 性能差.内存溢出等各种不可控问题就会出现.因此,如果对导出样式 ...
- pandas之时间重采样笔记
周期由高频率转向低频率称为降采样:例如5分钟股票交易数据转换为日交易数据 相反,周期也可以由低频转向高频称为升采样 其他重采样:例如每周三(W-WED)转换为每周五(W-FRI) import pan ...
- C#使用消息队列(MSMQ)
最近项目用到消息队列,找资料学习了下.把学习的结果 分享出来 首先说一下,消息队列 (MSMQ Microsoft Message Queuing)是MS提供的服务,也就是Windows操作系统的功能 ...
- java 爬虫:开源java爬虫 swing工具 Imgraber
1实现点: 1.返回给定URL网页内,所有图像url list 2.返回给定URL网页内,自动生成图像文件路径.txt 文件 3.返回给定URL网页内,下载txt文件指定的图片url,并将所有图像保存 ...