【发布时间】:2016-11-17 14:02:09
【问题描述】:
我正在使用 CMU-Cambridge 的 SLM 工具包对语言数据进行一些基线语言建模,但是当我运行其中一个构建的可执行文件时,我的系统在尝试执行其中一个命令时检测到缓冲区溢出。
基于this StackOverflow question,我注意到__gets_chk+0x179 导致了问题,并且我在源代码中发现了两次gets/fgets(evallm.c,也可用in this GitHub project someone made)但我不知道如何以适当/安全的方式修复它们。
错误信息的相关部分:
*** buffer overflow detected ***: /home/CMU-Cam_Toolkit_v2/bin/evallm terminated
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(__gets_chk+0x179)[0x7f613bc719e9]
Aborted
broken code
# declaration of input string variable
char input_string[500];
# occurence 1
...
while (fgets (wlist_entry, sizeof (wlist_entry),context_cues_fp)) { ... }
...
# occurence 2
...
while (!feof(stdin) && !told_to_quit) {
printf("evallm : ");
gets(input_string);
....
这个错误基本上是我给evallm命令的input_string太长了。通常它是从命令行调用的,你可以交互地传递参数。但是,我将所有参数与命令一起传送(如文档示例中所示),但显然有时我的参数名称占用了太多字节。当我将 input_string 的数组长度从 500 更改为 2000 时,问题就解决了(所以我猜错误是由于发生 2)。但我真的很想通过用getline() 替换gets() 来解决它,因为这似乎是正确的方法。还是用fgets() 替换它也是一种解决方案?如果是这样,我应该使用什么参数?
但是,在尝试替换 gets() 时,我总是遇到编译错误。我不是 C 程序员(Python、Java),也不熟悉 getline() 的语法,所以我在努力寻找正确的参数。
【问题讨论】:
-
你也可以使用 fgets,gets 的唯一区别是它有长度。
-
与您的
gets/fgets问题无关,但您可能有兴趣阅读Why is “while ( !feof (file) )” always wrong?。 -
@Someprogrammerdude 感谢您的提醒!该代码已经存在了很长一段时间(1999 年),所以我可以想象一些已弃用或“过时”的编程概念仍然存在。我会调查的!
-
“旧时编程概念”(你的意思是“风格,顺便说一句)”和“有问题的”/不安全代码之间有明显的区别。人们可以用汇编语言编写非常安全的代码。
-
@mbauwens:请点击我提供的链接。
标签: c getline buffer-overflow gets