漏洞描述:
使用查看展开式
(macroexpand-1 '(do-primes-2 (p 0 (random 100)) (format t "~d~t" p)))
返回结果:
(DO ((P (NEXT-PRIME 0) (NEXT-PRIME (1+ P)))) ((> P (RANDOM 100))) (FORMAT T "~d~t" P))
当运行展开式时,random将在每次进行循环的终止测试时被求值一次,
这样循环就不会在p大于一个初始给定的随机数时终止
而是在循环刚好生成一个小于或等于当前p值的随机数时循环才停止
由于循环的整体次数是随机的
因此它将产生一个与random所返回的统一分布相当不同的分布形式
修复方法:
只需要在生成代码时对end求值一次,并将其值保存在一个稍后会用到的变量值中。
在do循环中,用一个初始形式但没有步长形式来定义的变量会不在迭代过程中改变其值
因此将end放到初始变量中
;;;修复end多次求值漏洞
(defmacro do-primes-3 ( (var start end) &body body)
`(do ((ending-value ,end)
(,var(next-prime ,start) (next-prime(1+ ,var))))
((> ,var ending-value))
,@body))
经过这一调整,end的随机值漏洞被修复,但同时又引进了两个漏洞。
本节