gets函数,方便使它欢迎,安全性使它终被遗弃

前言:鱼与熊掌不可兼得,让gets函数被c11标准委员会终究狠下心选择丢弃的,我认为是它函数自身的安全问题,正如马斯洛需求层次理论提到的那样,安全是人的最底层需求层次,比起函数调用的方便,安全更让人觉得重要。
本篇博客的开头,以我写的“单词读取计算”程序一小部分为例,在键盘字符输入中,我们通常想到的是scanf和gets,gets函数相比于scanf,很好的解决了字符串读取空格即停止的特点,因此在某些场景下显得更为简单易用。
puts("hey ,please inter your word here"); gets_s(txt); ....... ...... puts(wors); puts("Done"); //这里不能用scanf

但是,这个优点,也成为了它的缺点,我们大胆的假设下,如果有一位调皮捣蛋的用户不厌其烦的准备在我们的程序输入一本柯林斯那么多的单词
gets函数,方便使它欢迎,安全性使它终被遗弃
文章图片

那么情况会怎样,可能的答案是缓冲区溢出(当然如果多余字符只是占用尚未使用的内存,就不会立即出现这个问题),如果放在网络安全术语里,那就是缓冲区溢出攻击。
gets函数还有一个典型的缺点,那就是攻击者可以很好的插入威胁代码,从而实现攻击目的。
这也因此c99标准委员会开始建议不再使用,随后,并在c11标准委员会以更强硬的态度选择了丢弃。
gets的丢弃自然让我们一些输入处理变得不方便,因此,我们选择了其他类似函数进行取代。
fgets():
会指定检测大小,但会将超出字符串的部分放入缓冲区,下一次调用时又会出现;
不会将换行符转为空字符,而是保留换行符并添加空字符’\0’,这会意味着字符串比原应有大1,或者读到遇到的第一个换行符为止。
gets_s()和fgets()的区别:
(1)gets_s()只从标准输入中读取数据,所以不需要第3个参数;
(2)如果gets_s()读到换行符,会丢弃它而不是存储它;这里和gets()函数几乎一样,完全可以用gets_s()替换gets()。
(3)如果gets_s()读到最大字符数都没有读到换行符或文件结尾,会执行以下几步。首先把目标函数数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着,调用依赖实现的“处理函数”(或你选择的其他函数),可能会中止或退出程序。
使用gets()函数不安全,它会擦除现有数据,存在安全隐患。gets_s()函数很安全,但是,如果并不希望程序终止或退出,就要知道如何编写特殊的“处理函数”。
所以,当输入与预期不符时,gets_s()完全没有fgets()函数方便、灵活。也许这也是gets_s()只作为C库的可选扩展的原因之一。
s_gets()
【gets函数,方便使它欢迎,安全性使它终被遗弃】自定义函数,要求是:读取整行输入并用空字符代替换行符,或者读取一部分输入,并丢弃其余部分

    推荐阅读