当前位置: 首页 > news >正文

【软件安全】fgets / strncpy / gets(不安全) / snprintf的对比 - 指南

fgets / strncpy / gets / snprintf 做一个系统对比
gets 禁用 历史罪人
fgets 输入首选
strcpy = 无上限写 → 典型溢出源(更糟)。
strncpy = 有上限但可能不终止 → 容易踩坑,不是“安全 strcpy”。
snprintf:格式化输出首选

总览速查表

函数典型签名作用上界控制是否保证以 '\0' 结尾常见坑点结论
fgetschar *fgets(char *s, int n, FILE *fp)从流(如 stdin)读入一行:最多读 n-1 个字节保证(若 n>0 且成功读到)可能把换行符也读进来;EOF/错误时返回 NULL首选的行输入;读完可“去掉换行”
strncpychar *strncpy(char *dst, const char *src, size_t n)拷贝最多 n 个字符:最多拷 n不保证(当 src 长度 ≥ n'\0'易产生无终止静默截断;短源会用 '\0' 填充剩余部分(低效)不推荐当作安全版 strcpy;仅在定长记录场景可用
getschar *gets(char *s)stdin 读一行:完全无上界不适用经典缓冲区溢出通道;已在 C11 移除禁止使用
snprintfint snprintf(char *s, size_t n, const char *fmt, …)格式化输出到缓冲区:最多写入 n-1 个可见字符保证(C99+ 当 n>0截断会发生;须检查返回值(需要的长度)首选的格式化写入;可用返回值做容量检查/重分配

1) fgets —— 读取字符串的首选输入 API

如何工作

返回值

常见坑

推荐用法(去掉尾部换行)

char buf[256];
if (fgets(buf, sizeof buf, stdin)) {
// 去掉尾部换行
buf[strcspn(buf, "\n")] = '\0';
// 使用 buf …
}

适用场景

  • stdin/文件读入文本行,有上界且自动 NUL 终止,最安全易用。

2) strncpy —— 不是“安全 strcpy”,更像“定长区域拷贝”

如何工作

  • src 拷贝最多n 个字符到 dst

    • src 长度 < n'\0' 填满剩余(零填充行为)。
    • src 长度 ≥ n不会写入终止 '\0'(这点最危险)。

返回值

  • 返回 dst 指针。

常见坑

  • src 较长时,dst'\0' 终止,随后对 dst 做字符串操作(如 printf("%s", dst) / strlen(dst))会越界读取
  • 被误当成“有界且总是安全”的复制函数;而零填充还会造成无谓的性能损耗

安全使用(若非用不可)

char dst[16];
strncpy(dst, src, sizeof dst - 1);
dst[sizeof dst - 1] = '\0';  // 手动确保终止

更好的替代

  • POSIX:strlcpy(dst, src, sizeof dst)(非标准,但常见于 BSD/部分 Linux 发行版)。
  • 纯标准场景:已知长度时用 memcpy + 手动 '\0';或直接用 snprintf

适用场景

  • 固定长度字段(如结构体里的定长数组,二进制记录),需要零填充才能对齐/复用的情况。不适合一般字符串复制

3) gets —— 历史罪人,已被删除

问题本质

  • 不进行边界检查,读入直到换行/EOF,极易缓冲区溢出
  • C11 起已从标准库移除;大多数现代编译器会报错或强烈警告。

替代

  • fgets(buf, sizeof buf, stdin)

结论

  • 永远不要使用

4) snprintf —— 安全的格式化输出首选

如何工作

示例:一次写入,检查截断

char buf[32];
int need = snprintf(buf, sizeof buf, "user=%s id=%d", user, id);
if (need < 0) {
// 格式化失败(很少见)
} else if ((size_t)need >= sizeof buf) {
// 截断发生:need 是所需大小(不含 '\0')
// 可选择:分配 need+1 大小重试
}

避免的坑

  • 忽视返回值,导致静默截断、关键信息丢失。
  • 传错 n(应当是缓冲区真实大小)。

适用场景

  • 一切“打印到字符串”的需求;替代 sprintf / vsprintf

该选谁?(实践建议)

  • 读文本行 → 用 fgets,随后按需去掉换行
  • 格式化拼接 → 用 snprintf,并检查返回值是否截断。
  • 二进制/定长记录拷贝 → 特殊场景可用 strncpy(随后手动终止或只作定长字段拷贝,不当作 C 字符串)。
  • 禁止gets(已移除,安全性极差)。

常见安全替代 & 小技巧


迷你示例:综合使用

// 从 stdin 读一行用户名,然后安全拼接日志前缀
char user[64];
if (!fgets(user, sizeof user, stdin)) {
fprintf(stderr, "input error\n");
return 1;
}
user[strcspn(user, "\n")] = '\0';  // 去掉尾部换行
char line[128];
int need = snprintf(line, sizeof line, "[login] user=%s", user);
if (need < 0) {
fprintf(stderr, "format error\n");
return 1;
}
if ((size_t)need >= sizeof line) {
fprintf(stderr, "truncated: needed %d bytes\n", need + 1);
// 可选择:动态分配 need+1 继续写
}
puts(line);

小结

  • gets禁用fgets读输入首选snprintf格式化输出首选(记得看返回值);strncpy不是安全版 strcpy,除定长记录外尽量避免,并手动补 '\0'
http://www.jsqmd.com/news/15797/

相关文章:

  • 实用指南:【论文阅读】Segment Anything
  • 2025 年最新推荐!刀闸阀生产厂家综合实力榜单出炉,涵盖陶瓷 / 国标 / 电动 / 气动 / 密封 / 手动 / 法兰 / 铸铁多类型产品
  • 2025 年最新推荐!选矿药剂生产厂家实力榜单,覆盖多矿石类型高效环保药剂品牌汇总石英长石 / 赤铁矿褐铁矿锂云母锂辉石 / 石墨煤矿的选矿药剂推荐
  • 2025 年最新推荐黄药厂家榜单:乙基 / 异丙基 / 异丁基 / 异戊基黄药及 38 号捕收剂等优质产品精选
  • 2025 年黑药生产厂家最新推荐榜单:丁铵丁钠等多型号黑药品牌综合实力解析与选购指南
  • Mac 桌面动态壁纸软件|Live Wallpaper 4K Pro v19.7 安装包使用教程(附安装包)
  • 直播平台代码,pc端微信授权登录的两种实现方式 - 云豹科技
  • 比特币区块空间经济学深度解析
  • 直播系统源码,js对象根据路径修改值 - 云豹科技
  • 2025 年离心泵厂家最新推荐榜单:涵盖化工 / 卧式多级 / 不锈钢等多类型,帮企业选优质设备
  • 直播系统开发,vue拖拽元素指令 - 云豹科技
  • 2025 年托盘厂家最新推荐榜,聚焦企业技术实力与市场口碑深度解析,筛选优质品牌助力企业采购
  • C# Avalonia 16- Animation- FrameBasedAnimation
  • 01.Python自动获取小说工具
  • 2025 年换热器厂家最新推荐榜:聚焦不锈钢、钛、哈氏合金等多材质及列管式等多类型设备,精选优质厂商助力企业采购决策
  • 2025 年最新推荐砂浆厂家排行榜:聚焦多类型砂浆产品,助力采购方精准选优质供应商
  • 2025 年电缆桥架厂家最新推荐榜:涵盖不锈钢 / 铝合金 / 热镀锌等类型,精选高性能企业助力选购
  • h5直播源码,如何实现一个简易播放器? - 云豹科技
  • 完整教程:【Linux】操作系统的认识
  • C# Avalonia 16- Animation- PathBasedAnimation
  • 2025年危险品运输公司权威推荐榜:安全高效,专业服务值得信赖!
  • 2025 年联轴器厂家最新推荐排行榜:聚焦万向、膜片、齿式等多类型产品,精选行业优质厂家
  • 2025 年换热器厂家最新推荐榜单:涵盖不锈钢钛哈氏合金等材质及列管式螺旋板等类型,为企业采购提供优质选择
  • 2025 年最新推荐!反应釜制造厂家榜单重磅发布,聚焦不锈钢钛合金哈氏合金等多类型设备优质厂商
  • 多模态、世界模型和主动智能丨Convo AIRTE2025
  • 2025年发电机组厂家推荐排行榜,柴油/燃气/船用/静音箱式/移动拖车/集装箱式/上柴/玉柴/潍柴/康明斯/沃尔沃/道依茨/帕金斯/MTU发电机组公司精选
  • 2025 防火隔断厂家最新推荐排行榜:甲级防火玻璃隔断厂家深度剖析,精选优质品牌助力采购决策
  • clickhouse数据库 数据插入 去重和覆盖
  • nacos客户端(接口调用者)如何感知被调用服务下线? (二)
  • 2025 水泥墩源头厂家最新推荐排行榜:光伏 / 交通 / 围挡等多品类优选,实力品牌权威榜单发布