作者およびメンテナー: Ivan Fratric、[email protected]
Copyright 2017 Google Inc. All Rights Reserved.
Apache License、Version 2.0(以下「本ライセンス」)に基づいてライセンスされています。 本ライセンスに準拠する場合を除き、本ファイルを使用することはできません。 本ライセンスのコピーは、次の場所から入手できます。
http://www.apache.org/licenses/LICENSE-2.0
適用法で要求される場合、または書面による合意がある場合を除き、本ライセンスに基づいて配布されるソフトウェアは、明示または黙示を問わず、いかなる種類の保証または条件もない「現状のまま」(AS IS)で配布されます。 本ライセンスに基づく特定の許可および制限については、本ライセンスを参照してください。
使用情報を表示するには、次のコマンドを実行します:
python3 generator.py --help
単一の .html サンプルを生成するには、次を実行します:
python generator.py --file <output file>
自作のテンプレートを使用して単一の .html サンプルを生成するには、次を実行します:
python generator.py --file <output file> --template <your custom template file>
1回の呼び出しで複数のサンプルを生成するには、次を実行します:
python generator.py --output_dir <output directory> --no_of_files <number of output files>
生成されたサンプルは指定されたディレクトリに配置され、fuzz-<number>.html(例: fuzz-00001.html、fuzz-00002.html など)という名前になります。複数のサンプルをまとめて生成する方が高速です。入力の文法ファイルの読み込みと解析が1回で済むためです。
generator.py にはメインスクリプトが含まれています。これは grammar.py をライブラリとして使用し、DOM ファジング用の追加ヘルパーコードを含んでいます。
grammar.py には、ほとんどアプリケーションに依存しない生成エンジンが含まれており、他の(つまり DOM 以外の)生成ベースのファザーでも使用できます。ライブラリとして使用できるため、その使用方法は後述の別セクションで説明します。
.txt ファイルには文法定義が含まれています。主要なファイルは html.txt、css.txt、js.txt の3つで、それぞれ HTML、CSS、JavaScript の文法が含まれています。これらのルート文法ファイルは、他のファイルの内容を含む場合があります。
カスタム文法で生成エンジンを使用するには、次の Python コードを使用できます:
from grammar import Grammar
my_grammar = Grammar()
my_grammar.parse_from_file('input_file.txt')
result_string = my_grammar.generate_symbol('symbol_name')
以下のセクションでは、文法ファイルの構文について説明します。
Domato は、以下に指定するシンプルな形式の文脈自由文法が与えられると、その文法からサンプルを生成するエンジンに基づいています。
文法は、次の基本形式のルールの集合として記述されます:
<symbol> = a mix of constants and <other_symbol>s
各文法ルールは、等号で区切られた左辺と右辺で構成されます。左辺にはシンボルが含まれ、右辺にはそのシンボルをどのように展開できるかの詳細が含まれます。シンボルを展開するとき、右辺のすべてのシンボルは再帰的に展開され、シンボルではないものはすべてそのまま出力にコピーされます。1つのルールを入力ファイルの複数行にまたがって記述することはできないことに注意してください。
CSS 文法の一部の簡略化した例を考えてみましょう:
<cssrule> = <selector> { <declaration> }
<selector> = a
<selector> = b
<declaration> = width:100%
その文法を解析して 'cssrule' を生成するように文法エンジンに指示すると、次のいずれかが出力されます:
a { width:100% }
または
b { width:100% }
'selector' シンボルには2つのルールがあることに注意してください。このような場合、'selector' の生成を求められたジェネレータは、使用するルールをランダムに選択します。また、'p' 属性を使用してルールの確率を指定することもできます。例:
<selector p=0.9> = a
<selector p=0.1> = b
この場合、文字列 'a' は 'b' よりも頻繁に出力されます。
確率に加えて、シンボルに適用できる他の属性もあります。これらは別のセクションに記載されています。
HTML サンプルを生成する別の例を考えてみましょう:
<html> = <lt>html<gt><head><body><lt>/html<gt>
<head> = <lt>head<gt>...<lt>/head<gt>
<body> = <lt>body<gt>...<lt>/body<gt>
文法構文では '<' と '>' が特別な意味を持つため、ここでは代わりに <lt> と <gt> を使用していることに注意してください。これらのシンボルは組み込みであり、ユーザーが定義する必要はありません。すべての組み込みシンボルの一覧は別のセクションに記載されています。
プログラミング言語コードの生成には同様の構文を使用できますが、いくつかの違いがあります。プログラミング言語文法の各行は出力の1行に対応します。そのため、文法構文はより自由形式になり、さまざまなプログラミング言語の構造を表現できます。次に、行が生成されるとき、その行の出力に加えて1つ以上の変数が作成されることがあり、それらの変数は他の行を生成するときに再利用できます。ここでも、簡略化した例を見てみましょう:
!varformat fuzzvar%05d
!lineguard try { <line> } catch(e) {}
!begin lines
<new element> = document.getElementById("<string min=97 max=122>");
<element>.doSomething();
!end lines
エンジンに5行を生成するよう指示すると、次のような出力になります:
try { var00001 = document.getElementById("hw"); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
try { var00002 = document.getElementById("feezcqbndf"); } catch(e) {}
try { var00002.doSomething(); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
次の点に注意してください:
element> の代わりに <new element> を使用しました。これは、'element' シンボルを生成する代わりに、'element' 型の新しい変数を作成するようにジェネレータに指示します。string> は組み込みシンボルの1つなので、定義する必要はありません。行の最初の '#' 文字以降はすべてコメントと見なされます。例:
#This is a comment
文法構文には、どのルールが非再帰的であり、最大再帰レベルに達した場合でも安全に使用できるかをファザーに伝える方法があります。これは 'nonrecursive' 属性を使用して行われます。例を以下に示します。
!max_recursion 10
<test root=true> = <foobar>
<foobar> = foo<foobar>
<foobar nonrecursive> = bar
まず、任意の '!max_recursion' ステートメントが最大再帰深度(デフォルトは50)を定義します。'foobar' の2番目の生成規則が非再帰としてマークされていることに注意してください。最大再帰レベルに達した場合、ジェネレータは 'foobar' シンボルに対して非再帰ルールの使用を強制するため、無限再帰が防止されます。
Domato では、文法のインクルードとインポートは異なる2つのコンテキストです。
インクルードはよりシンプルです。次のように使用できます:
!include other.txt
これにより、other.txt のルールが現在解析中の文法に含まれます。
インポートは少し異なる動作をします:
!import other.txt
これはパーサーに新しい Grammar() オブジェクトを作成するように指示し、特別な <import> シンボルを使用して現在の文法から参照できるようにします。例:
<cssrule> = <import from=css.txt symbol=rule>
インポートとインクルードは名前空間の観点で考えることができます: !include はインクルードされた文法を単一の名前空間に配置しますが、!import は新しい名前空間を作成し、<import> シンボルと 'from' 属性で指定された名前空間を使用してアクセスできます。
文法内でカスタム Python コードを呼び出したい場合があります。たとえば、エンジンを使用して HTTP レスポンスを生成し、ボディの長さを 'Size' ヘッダーに一致させたいとします。これは通常の文法ルールでは不可能なことなので、次のようにカスタム Python コードを含めることで実現できます:
!begin function savesize
context['size'] = ret_val
!end function
!begin function createbody
n = int(context['size'])
ret_val = 'a' * n
!end function
<foo root> = <header><cr><lf><body>
<header> = Size: <int min=1 max=20 beforeoutput=savesize>
<body> = <call function=createbody>
Python 関数は '!begin function <function_name>' コマンドと '!end function' コマンドの間に定義されます。関数は2つの方法で呼び出すことができます: 'beforeoutput' 属性を使用する方法と、<call> シンボルを使用する方法です。
シンボルに 'beforeoutput' 属性を指定すると、そのシンボルが展開され、展開結果がサンプルに出力される直前に、対応する関数が呼び出されます。展開結果は ret_val 変数で関数に渡されます。関数は ret_val を変更したり、後で使用するために保存したり、その他の操作を実行したりできます。
特別な <call> シンボルを使用する場合、言語生成中にそのシンボルが検出されると、関数('function' 属性で指定)が呼び出されます。関数が ret_val に格納した値は展開結果と見なされます(ret_val がサンプルに含まれます)。
Python コードは次の変数にアクセスできます:
context - サンプル生成全体を通して渡される辞書です。値(上記の例でサイズを保存するなど)を保存し、後続で適用されるルールで取得するために使用できます。attributes - 現在処理中のシンボルに対応する辞書です。関数にパラメータを渡すために使用できます。たとえば、<call function=func foo=bar> のようにして関数を呼び出した場合、attributes[‘foo’] は 'bar' に設定されます。ret_val - 関数呼び出しの結果として出力される値です。<call> シンボルを使用して関数を呼び出す場合は空の値に初期化され、それ以外の場合はシンボルによって生成された値に初期化されます。次のシンボルには特別な意味があり、ユーザーが再定義すべきではありません:
<lt> - '<' 文字<gt> - '>' 文字<hash> - '#' 文字<cr> - CR 文字<lf> - LF 文字<space> - 空白文字<tab> - タブ文字<ex> - '!' 文字<char> - 'code' 属性を使用して任意の ASCII 文字を生成するために使用できます。たとえば <char code=97> は 'a' に対応します。指定されていない場合はランダムな文字が生成されます。'min' 属性と 'max' 属性をサポートします。<hex> - ランダムな16進数の桁を生成します。<int>、<int 8>、<uint8>、、、、、、 - ランダムな整数を生成するために使用できます。生成される整数の範囲を制限するために使用できる 'min' 属性と 'max' 属性をサポートします。また、テキスト出力の代わりにリトル/ビッグエンディアン形式のバイナリ出力にする 'b' 属性と 'be' 属性もサポートします。次の属性がサポートされています:
<call> シンボルで使用されます。詳細は「Python コードのインクルード」セクションを参照してください。Domato で発見されたバグの一部:
これは Google の公式製品ではありません。
<int16><uint16><int32><uint32><int64><uint64><float>、<double> - ランダムな浮動小数点数を生成します。'min' 属性と 'max' 属性をサポートします(指定しない場合は0と1)。出力をバイナリにする 'b' 属性もサポートします。<string> - ランダムな文字列を生成します。生成される最小/最大文字コードを制御する 'min' 属性と 'max' 属性、および文字列の長さを制御する 'minlength' 属性と 'maxlength' 属性をサポートします。<htmlsafestring> - HTML メタ文字がエスケープされる点を除いて <string> と同じです。文字列を HTML テキストまたは属性値の一部として埋め込んでも安全になります。<lines> - 指定された数('count' 属性経由)のコード行を出力します。例については、プログラミング言語コードの生成に関するセクションを参照してください。<import> - 別の文法からシンボルをインポートします。詳細は外部文法のインクルードに関するセクションを参照してください。<call> - function 属性に対応するユーザー定義関数を呼び出します。詳細は文法への Python コードのインクルードに関するセクションを参照してください。