C语言高危越界函数:gets / getwd 漏洞与替换方案
2026/9/3 15:31:45 网站建设 项目流程

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);
参数详解(通俗直白、考试原话)
  1. buf:字符缓冲区数组,用来存放读取到的字符串;
  2. size:缓冲区最大长度,传入 sizeof(buf),是防越界的核心,限制最多读取的字节数;
  3. 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. 保留优点:同样支持读取空格、TAB;

2. 修复漏洞:带长度限制,超长自动截断,绝不越界;

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:程序初始化获取工作目录、拼接日志路径、定位配置文件、目录权限校验。

三、核心总结

  1. gets / getwd 共性:无长度参数、无边界校验,必然内存越界,标准废弃;
  2. fgets / getcwd 共性:强制携带长度参数,超长截断/报错,杜绝非法内存访问;
  3. 所有缓冲区读写,必须指定有效长度,禁止无边界操作。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询