C语言高危越界函数:gets / getwd 漏洞与替换方案

发布时间:2026/9/3 15:31:57
C语言高危越界函数:gets / getwd 漏洞与替换方案 gets、getwd 是 C 语言两个经典高危废弃函数核心问题一致没有缓冲区长度校验会造成内存越界、非法内存访问、程序崩溃正式工程、考试、项目中一律禁用。一、gets 函数字符串输入越界1. 函数原型#include stdio.h char *gets(char *s);2. 基础用法char str[10]; gets(str); // 数组名等价于 str[0]传数组首地址3. 核心特性1. 可以读取空格、TAB 等空白字符仅回车\n结束输入2. 自动丢弃换行符不会把 \n 存入数组自动补\0收尾3. 和 scanf 区别scanf 遇到空格、TAB、回车就终止无法读取带空格字符串gets 可以。4. 致命漏洞废弃原因gets没有长度参数完全不检查数组容量。当用户输入字符串超过数组最大长度函数会持续向后写入内存造成数组越界、篡改相邻变量、非法内存访问、程序段错误崩溃。C11 标准已彻底删除 gets 函数。5. 安全替代fgets函数原型char *fgets(char *buf, int size, FILE *stream);参数详解通俗直白、考试原话buf字符缓冲区数组用来存放读取到的字符串size缓冲区最大长度传入 sizeof(buf)是防越界的核心限制最多读取的字节数stream指定数据的读取来源stdin 全称标准输入流C语言默认绑定键盘设备。直白话 fgets 是通用函数既能读文件、也能读键盘写 stdin 告诉程序这次不从文件读从键盘读取用户输入。控制台键盘输入场景第三参数固定写 stdin。❌ 错误代码gets 越界漏洞char buf[10]; gets(buf); // 无长度限制输入超过9个字符直接越界✅ 正确代码fgets 安全写法char buf[128]; fgets(buf, sizeof(buf), stdin);6. fgets 与 gets 关键区别1. 保留优点同样支持读取空格、TAB2. 修复漏洞带长度限制超长自动截断绝不越界3. 唯一不同fgets 会把回车\n读入数组缓冲区。7. 适用场景gets全线禁用存在高危越界漏洞fgets读取带空格的键盘字符串、文本数据、配置文件内容scanf仅适合读取无空格的数字、单个单词。二、getwd 函数工作路径越界1. 核心漏洞getwd 仅接收数组指针无长度校验参数。函数默认按系统最大路径长度写入内存若自定义数组空间过小会直接溢出、非法内存访问、程序崩溃POSIX.1-2008 标准已废弃。2. 安全替代getcwd函数原型char *getcwd(char *buf, size_t size);参数详解buf存储当前工作路径的字符数组size手动指定数组真实长度限制最大写入字节数。防越界原理若当前路径字符串长度大于 size-1函数直接返回 NULL、报错不会写入溢出内存从根源杜绝越界。返回值成功返回路径字符串首地址失败返回 NULL自动设置错误码 errno。❌ 错误代码getwd 越界漏洞char path[32]; getwd(path); // 路径过长直接越界触发段错误✅ 正确代码getcwd 安全写法char path[128]; getcwd(path, sizeof(path)); // 带长度限制超长报错不越界 printf(当前路径%s\n, path);3. 进阶用法get_current_dir_name无需手动定义数组、无需预估缓冲区大小函数内部自动 malloc 足够内存存储绝对路径。注意使用后必须 free 释放内存防止内存泄漏必须前置定义宏#define _GNU_SOURCE且宏要写在头文件之前。#define _GNU_SOURCE #include unistd.h #include stdio.h #include stdlib.h int main() { char *path get_current_dir_name(); if(path ! NULL) { printf(当前路径%s\n, path); free(path); } return 0; }4. 适用场景getwd全线禁用getcwd程序初始化获取工作目录、拼接日志路径、定位配置文件、目录权限校验。三、核心总结gets / getwd 共性无长度参数、无边界校验必然内存越界标准废弃fgets / getcwd 共性强制携带长度参数超长截断/报错杜绝非法内存访问所有缓冲区读写必须指定有效长度禁止无边界操作。