Fuzzing用ファイルジェネレータ
30分プログラム、その424。ファジング:ブルートフォースによる脆弱性発見手法を読んでいるときに、テスト用のテストデータのルールをもっと宣言的に書ければいいのに、と思ったので試してみる。
例えば、
def point = "(" ~ digit ~ "," ~ digit ~ ")"
と書くと、"(<数字>,<数字>)"という形のデータを大量に生成できるようにしたい。書き方はscala.util.parsing.combinator._にあるコンビネータパーサを意識してる。
最初は、設定を受けとってT型のデータを生成する、みたいにすごい抽象的なクラスも作っていたけど、だんだん分けがわからなくなってきたので、思い切って引数なし、生成するのはList[String]固定にしてみた。
使い方
class Points extends Fuzzings { def point = "(" ~ digit ~ "," ~ digit ~ ")" } val points = new Points for(p <- points.point()){ println(p) }
ソースコード
class Fuzzings { // Abstract Fuzzing abstract class Fuzz { p => def apply() : List[String] def ~(q : Fuzz) : Fuzz = new Fuzz{ def apply = for(x <- p(); y <- q()) yield (x+y) } def |(q : Fuzz) : Fuzz = new Fuzz{ def apply = p() ::: q() } } // String def string(s : String) : Fuzz = new Fuzz{ def apply() = List(s) } implicit def literal(s : String) : Fuzz = string(s) // Digit def digit : Fuzz = new Fuzz{ def apply() = (0 to 9).map(_.toString).toList } def lower() : Fuzz = new Fuzz{ def apply() = ('a' to 'z').map(_.toString).toList } def upper() : Fuzz = new Fuzz{ def apply() = ('A' to 'Z').map(_.toString).toList } } class Points extends Fuzzings { def point = "(" ~ digit ~ "," ~ digit ~ ")" } val points = new Points for(p <- points.point()){ println(p) }