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 ...
随机推荐
- 将自己的项目作为jar包发布到maven中央仓库
maven版本是3.5.0,jdk是1.8(注意,不是说项目是1.8就行,必须是环境变量里的也是,不能超过1.8,否则一大堆问题,执行mvn前用javac -version看下版本) 一:先在sona ...
- TCP/IP协议图--TCP/IP基础
1. TCP/IP 的具体含义 从字面意义上讲,有人可能会认为 TCP/IP 是指 TCP 和 IP 两种协议.实际生活当中有时也确实就是指这两种协议.然而在很多情况下,它只是利用 IP 进行通信时所 ...
- python实战项目 — 爬取中国票房网年度电影信息并保存在csv
import pandas as pd import requests from bs4 import BeautifulSoup import time def spider(url, header ...
- triples I(按位或运算及3的特性)(2019牛客暑期多校训练营(第四场)D)
示例1: 输入: 2 3 7 输出: 1 32 3 6 说明:3=3, (3|6)=7 题意:输出尽可能少的数字,他们的按位或结果为输入的数字a. 题解:(表示看不懂题解,看山东大佬的代码看懂的)首先 ...
- 【springcloud】1.微服务之springcloud-》eureka源码分析之请叫我灵魂画师。。。
- 在论坛中出现的比较难的sql问题:17(字符分拆2)
原文:在论坛中出现的比较难的sql问题:17(字符分拆2) 最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了. 所以,觉得有必要记录下来 ...
- C#导入Excel表格功能aspx.cs(代码)
using System; using System.Data; using System.Configuration; using System.Collections; using System. ...
- 升级win10 1903版后,vmware打开虚拟机黑屏的解决办法
按照网上给的方法(1-3),又增加了几步(从4开始,只在我自己电脑上实践过): 1. 打开cmd,执行以下命令 netsh winsock reset 2. 重启电脑 3. 以管理员身份执行vmwar ...
- sqlserver2008+日志收缩sql语句命令
USE[master] GO ALTER DATABASE 数据库 SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE 数据库 SET RECOVER ...
- IIS发布问题解决
一. HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure ://安装AspNetCoreModule托管模块后执行1. net stop wa ...