2015-09-10 12 views
5

入力ファイル(ユーザによって変更されている場合もあれば変更されていない可能性もあります)から文字列を読み込みたいとします。私はこの文字列を、固定数の引数で呼び出されるフォーマット指令として扱いたいと思います。しかし、私はいくつかのフォーマット指令(特に~/が頭に浮かぶ)が関数呼び出しを挿入するために潜在的に使用される可能性があることを理解しており、このアプローチは本質的に安全ではありません。Common Lispで書式指令を安全に解析する

Common Lispの中のデータを解析するreadを使用する場合、言語が#.コードインジェクションを無効にするnilに設定することができる*read-eval*動的変数を提供します。私は、フォーマットインジケータの内部でコードインジェクションや任意の関数呼び出しを防ぐようなものを探しています。

答えて

4

ユーザーがカスタムコードを導入することはできず、文字列を書式設定するだけであれば、print-objectの問題を回避できます。 with-standard-io-syntax(またはカスタマイズされたバージョン)を使用して、生成する正確な種類の出力を制御することを覚えておいてください(*print-base*などを考えてください)。

入力文字列をスキャンして~/(ただし、~~/は有効です)の存在を検出し、ブラックリスト化された構造を含む形式の解釈を拒否することができます。 しかし、分析が難しく、実行時に行動する必要があるかもしれません。

たとえば、フォーマット文字列の形式が間違っていると、エラーが発生する可能性があります。これを処理する必要があります(また、期待される引数に不正な値を与える可能性があります)。

ユーザーが悪意のない場合でも、あなたはまた、反復構築物での問題を持つことができます。~:*は現在の引数を巻き戻しているため

~{<X>~:*~} 

は...停止することはありません。これを処理するには、<X>が何かを印刷するかどうかを検討する必要があります。あなたは、これらの戦略の両方を実現することができます。

  • は、(文字列バッファへの書き込みなど)時間のフォーマットが
  • は、基になるストリームリーチエンド・オブ・ファイルが多すぎる書き込ん持っかかる制限するためのタイムアウトを持っています。

私は現在表示されない他の問題があるかもしれないので注意してください。

+1

ありがとうございました。私は無限ループ問題については考えていませんでした。このような問題があると、 'format'を微調整しようとするよりも、フォーマット指定子のために自分のマイクロ言語を書くことになるでしょう。 –

+0

@SilvioMayoloこれも良いアプローチです。しかし、他のフォーマットが存在するかどうかを確認するのに時間をかけてください:私は 'cl-interpol'について考えていますが、他のフォーマットがあるかもしれません。がんばろう! – coredump

+1

反復構造に関する素晴らしい点! –

3

気にする必要があるのは〜/だけではありません。かなりのプリンタ機能にはコード拡張の可能性がたくさんあります。〜Aでもオブジェクトにはのprint-objectのメソッドが定義されている可能性があります。例えば、

(defclass x()()) 

(defmethod print-object ((x x) stream) 
    (format *error-output* "Executing arbitrary code...~%") 
    (call-next-method x stream)) 

CL-USER> (format t "~A" (make-instance 'x)) 
Executing arbitrary code... 
#<X {1004E4B513}> 
NIL 

私はあなたが重要と考える、とだけのものが挙げられるどんな基準使用して、ディレクティブは安全であるあなた自身のために定義する必要があると思います。

関連する問題