2012-02-23 9 views
14

私はF#を使用してWebアプリケーションを開発しています。 SQL、XSS、その他の脆弱性からユーザー入力文字列を保護することを考えています。二つの単語でF#の文字列のコンパイル時の制約.Unit of Measureと同様ですか?

は、私は、例えば、

多くの言語がそれを持っているなど、XHTML、私はSQL、URL、XSSを表すものと無地の文字列を区別できるようになるいくつかのコンパイル時間の制約を必要としますRubyのネイティブ文字列補間機能#{...}
F#では、Measure単位は非常によく機能するようですが、数値型でのみ使用できます。
ランタイム UoM (link)を使用して解決策がいくつかありますが、それは私の目標のオーバーヘッドだと思います。

私はFSharpPowerPackに見てきた、そして文字列の類似した何かを思い付くことは可能と思われる:

[<MeasureAnnotatedAbbreviation>] type string<[<Measure>] 'u> = string 
// Similarly to Core.LanguagePrimitives.IntrinsicFunctions.retype 
[<NoDynamicInvocation>] 
let inline retype (x:'T) : 'U = (# "" x : 'U #) 
let StringWithMeasure (s: string) : string<'u> = retype s 

[<Measure>] type plain 
let fromPlain (s: string<plain>) : string = 
    // of course, this one should be implemented properly 
    // by invalidating special characters and then assigning a proper UoM 
    retype s 

// Supposedly populated from user input 
let userName:string<plain> = StringWithMeasure "John'); DROP TABLE Users; --" 
// the following line does not compile 
let sql1 = sprintf "SELECT * FROM Users WHERE name='%s';" userName 
// the following line compiles fine 
let sql2 = sprintf "SELECT * FROM Users WHERE name='%s';" (fromPlain userName) 

:それはただのサンプルです。 SqlParameterを使用して提案しないでください。 :-)

私の質問です:それを行うまともなライブラリはありますか?構文砂糖を追加する可能性はありますか?
ありがとうございます。

更新1:私はコンパイル時の制約があります、感謝します。

更新2:実行時のオーバーヘッド(タプル、構造体、識別された共用体など)を避けようとしています。

+2

参照してください。面白いハスケルが問題に取り組むためのhttp://blog.moertel.com/articles/2006/10/18/a-type-based-solution-to-the-strings-problem – kvb

+1

これを実装しようとすれば、私はそれを見ることに興味があるでしょう! – Benjol

+2

@kvb、あなたのリンクは死んでしまったようです... 自分自身のために働くリンクを入れましょう:) http://blog.moertel.com/posts/2006-10-18-a-type-based- solution-to-the-strings-problem.html – moudrick

答えて

2

あなたがしようとしていることを伝えるのは難しいです。あなたは、「実行時の制約が必要です」と言ったが、厳密にはコンパイル時間である測定単位でこれを解決することを望んでいる。簡単な解決策は、クラス(XXXSqlXmlなど)を入力して入力を検証することです。

type SafeSqlString(sql) = 
    do 
    //check `sql` for injection, etc. 
    //raise exception if validation fails 
    member __.Sql = sql 

コンパイル時ではなく、実行時の安全性を提供します。しかし、それはシンプルで、自己文書化であり、F#コンパイラソースを読み込んで動作させる必要はありません。

しかし、あなたの質問に答えるために、測定単位でこれを行う方法はありません。構文的な砂糖がある限り、それをモナドにカプセル化することができるかもしれませんが、それはそれがより鈍い、より少なくないと思うと思います。

+0

しかし、あなたの質問には実行時の制約が必要だと言われています。しかし、私は両方の可能性に取り組もうとしました。 – Daniel

+0

ああ申し訳ありませんが、これを指摘してくれてありがとう! – bytebuster

3

理論的には、それが文字列で、コンパイル時のチェックの様々な種類を提供するために、「単位」を使用することが可能です(この文字列「汚染された」ユーザの入力、または消毒のですか?このファイル名は、相対または絶対のですか?...)

私は個人的にはあまりにも実用的ではないことが分かりました。「ストリング」を使用する既存のAPIが数多くあり、ここからそこへデータを配管するための手間と手作業による変換が必要です。

文字列はエラーの巨大な原因であり、文字列の汚染/正規化などを扱う型システムは、エラーを減らすための静的型付けにおける次の飛躍の1つになりますが、 15年の地平線のように。私はF#UoMのアプローチを試してみる人に興味があるでしょうか?

+0

私はそれを完全には理解していないかもしれませんが、これに対するUoMのアプローチは、ラッパークラスを超えて検証を提供しますか?型安全性のレベルは同じように見えますが、後者は実装するのがはるかに容易です(現在)。 – Daniel

+0

ダニエル:理由は数値型の理由とよく似ています。 UoMは、異なる_purposes_を有する偶然のミキシング変数を防止するが、同じ_runtime_typeとして格納する。 Joelによって書かれた "code smell"問題の完全な説明があります。 – bytebuster

+0

異なる文字列型を混在させたくないと理解していますが、さまざまな方法(ラッパークラス、など)。私は、これに対するUoMのアプローチの利点についてはっきりしていません。 – Daniel

3

最も簡単な解決策は

"hello"<unsafe_user_input> 

を行うことができないためには、

type mystring<'t>(s:string) = 
    let dummyint = 1<'t> 

のような文字列をラップするために、いくつかの数値型を持っていたタイプを記述することです次に、あなたは、コンパイル時のチェックを持っていますあなたの弦の上に

+1

クラスの代わりに構造体を使用して、ラッパーの(間違いなく)小さなオーバーヘッドを避けることをお勧めします。 – Joh

2

差別化された組合を使うことができます:

type ValidatedString = ValidatedString of string 
type SmellyString = SmellyString of string 

let validate (SmellyString s) = 
    if (* ... *) then Some(ValidatedString s) else None 

コンパイル時のチェックが行われ、2つの検証済みの文字列を追加しても検証された文字列は生成されません。

参照型の追加されたオーバーヘッドが大きすぎる場合は、代わりに構造体を使用できます。

+2

提案していただきありがとうございます。問題は、DUがクラスであることです。あなたはそれを構築することを避けることはできません。 'int 'は実際には実行時に 'int'であり、オーバーヘッドはまったくありません。 – bytebuster

7

少し遅れて、私はこれらのワンライナーは、あなたの目標のために互換性があると考えている(私は2月23日と11月30日の間に1ビットだけ異なっている時刻の形式があります確信している):

type string<[<Measure>] 'm> = string * int<'m> 

type string<[<Measure>] 'm> = { Value : string } 

type string<[<Measure>] 'm>(Value : string) = struct end 
+0

答えてくれてありがとうございますが、最初のものは 'Tuple <_,_>'を構築することを強制し、後者のものは実際に 'struct'です。私はランタイムオーバーヘッドを避けようとしています。 – bytebuster

関連する問題