几天前,有几个关于缓冲区溢出漏洞的问题(例如Java是否有缓冲区溢出?,Secure C和大学 - 经过缓冲区溢出训练,仅举几例),这些问题可能发生在C等命令式编程语言中.
在函数式编程中,(从我尝试Haskell的非常有限的曝光),我可以看到缓冲区溢出等漏洞不会发生,因为这些问题是由于改变程序状态或某个区域而导致的.记忆.(如果我错了,请纠正我.)
如果不考虑编译器,解释器或执行环境中存在的漏洞的可能性,功能编程范例中是否存在任何类型的安全漏洞?功能编程中是否存在任何特定类型的漏洞,而不是命令式编程中存在哪些漏洞?
如果程序员没有预料到[某些输入]会导致[程序]消耗超过可用资源,那么这就是可能的DoS形式的漏洞.这是我见过的所有图灵完备语言的弱点,但是Haskell的懒惰使得更难以推断出计算涉及的内容.
作为一个(相当做作的)例子,
import Control.Monad (when) import System (getArgs) main = do files <- getArgs contents <- mapM readFile files flip mapM_ (zip files contents) $ \(file, content) -> when (null content) $ putStrLn $ file ++ " is empty"
天真的程序员可能会认为,"Haskell是懒惰的,所以它不会打开并读取文件,直到它需要","Haskell被垃圾收集,因此一旦完成文件,就可以关闭文件句柄".不幸的是,这个程序实际上只会同时打开大量文件(特定于实现),只有空文件才会关闭文件句柄(实现的活泼规则的副作用):
$ ghc --make -O2 Test [1 of 1] Compiling Main ( Test.hs, Test.o ) Linking Test ... $ strace -etrace=open,close ./Test dir/* /dev/null ... open("dir/1", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 3 open("dir/2", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4 open("dir/3", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 5 open("dir/4", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 6 open("dir/5", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 7 ... open("/dev/null", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 255 close(255) /dev/null is empty $
您可能不会期望-EMFILE"太多打开文件"错误发生.
就像我说的,这是一个人为的例子,也可能在其他语言中发生,但它更容易错过Haskell中的某些资源使用.
功能语言由于其执行模型而具有不受重视的"通过默默无闻的安全性"优势.如果你看一下C程序中的安全漏洞,它们会利用弱类型系统,指针操作和缺少边界检查,但更重要的是,它们利用了一个易于理解的直接执行模型.例如,您可以在C中可靠地粉碎堆栈,因为只需获取局部变量的地址就可以相对容易地知道堆栈的位置.许多其他漏洞依赖于对执行模型的类似的低级理解.
相比之下,如何将功能代码编译成二进制文件并不是那么明显,因此设计执行注入代码或访问特权数据的方法并不是那么容易.具有讽刺意味的是,执行模型的模糊性通常被认为是函数式语言的弱点,因为程序员并不总是对代码的执行方式有很好的直觉.