2009-05-05 13 views
0

私は今、サーバーを立ち上げました。この機能が原因だと思います。誰が問題が何であるか教えてもらえますか?私はそれを把握することができません:これはなぜ無限ループですか?

Public Function CleanText(ByVal str As String) As String  
'removes HTML tags and other characters that title tags and descriptions don't like 
    If Not String.IsNullOrEmpty(str) Then 
     'mini db of extended tags to get rid of 
     Dim indexChars() As String = {"<a", "<img", "<input type=""hidden"" name=""tax""", "<input type=""hidden"" name=""handling""", "<span", "<p", "<ul", "<div", "<embed", "<object", "<param"} 

     For i As Integer = 0 To indexChars.GetUpperBound(0) 'loop through indexchars array 
      Dim indexOfInput As Integer = 0 
      Do 'get rid of links 
       indexOfInput = str.IndexOf(indexChars(i)) 'find instance of indexChar 
       If indexOfInput <> -1 Then 
        Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1 
        Dim indexRightBracket As Integer = str.IndexOf(">", indexOfInput) + 1 
        'check to make sure a right bracket hasn't been left off a tag 
        If indexNextLeftBracket > indexRightBracket Then 'normal case 
         str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) 
        Else 
         'add the right bracket right before the next left bracket, just remove everything 
         'in the bad tag 
         str = str.Insert(indexNextLeftBracket - 1, ">") 
         indexRightBracket = str.IndexOf(">", indexOfInput) + 1 
         str = str.Remove(indexOfInput, indexRightBracket - indexOfInput) 
        End If 
       End If 
      Loop Until indexOfInput = -1 
     Next 
    End If 
    Return str 
End Function 

答えて

5

これは簡単ではないでしょうか? (OK、私はそれが掲示コードと同一でないことを知っている):

public string StripHTMLTags(string text) 
{ 
    return Regex.Replace(text, @"<(.|\n)*?>", string.Empty); 
} 

(VB.NETへの変換は簡単でなければなりません!)

注:あなたは、多くの場合、これを実行している場合、2点の性能改善がそこにありますRegexにすることができます。

1つは、あらかじめコンパイルされた式を使用し、少し書き直す必要があります。

2番目の方法は、正規表現の非キャプチャ形式を使用することです。 .NETの正規表現は、(?:)構文を実装しています。これにより、キャプチャされたテキストのパフォーマンス上のペナルティを逆参照として記憶することなく、グループ化を行うことができます。この構文を使用して、上記の正規表現に変更することができます単純な<a<a<a場合、あるいは<a>Test</a>のために動作するようには思えない

@"<(?:.|\n)*?>" 
+0

彼はすべてのタグ、または特定のタイプのすべてのタグを削除していませんが、これはおそらくもっと簡単です。 –

+0

私はちょうどそれに気付き、私のポストを編集し、あなたのコメントが表示されたのを見た! –

0

ちょうど推測ですが、これは、犯人のようですか?その文字列が見つかった場合 値のインデックス位置、または-1そうでない場合 - indexOfInput = str.IndexOf(indexChars(i))が「Microsoft docsパー

、戻り値にindexChar

のインスタンスを見つけます。値が空の場合、戻り値は0です。

したがって、おそらくindexOfInputが0に設定されていますか?

+0

関数の最初の行は次のようになります。If Not String.IsNullOrEmpty(str)、この場合の処理​​になります... – Jason

0

コードで文字列を消去しようとするとどうなりますか<a

私が読んだところでは、位置0でindexCharを見つけましたが、次にindexNextLeftBracketとindexRightBracketはどちらも0になり、else条件に入り、位置-1に ">"を挿入します。最初に文字列><aを与えます。新しいindexRightBracketは0になるので、位置0から0文字を削除して、><aのままにしておきます。その後、コード内で<aが再び見つかると、無限にメモリを消費するループが発生します。

私が間違っていても、これらのエッジケースが正しく機能することを確認するために、ユニットテストを行う必要があります。それはまた、私がオフベースの場合、実際のループコードを見つけるのに役立ちます。

一般的に言えば、この特定のバグを修正しても、決して非常に堅牢になることはありません。 HTMLの解析は難しく、HTMLブラックリストには常に穴があります。たとえば、実際に<input type="hidden" name="tax"タグを取得する場合は、<input name="tax" type="hidden"と書いて、コードで無視されます。より良い賭けは、実際のHTMLパーサーが関与するようにし、実際に必要なタグの(非常に小さい)サブセットのみを許可することです。あるいは、他の形式のマークアップを使用して、すべてのHTMLタグを取り除いてください(実際のHTMLパーサを使用して再度記述します)。

0

私は実際のコンパイラで実行しなければならないが、マインドプライヤはstr = str.Remove(indexOfInput, indexRightBracket - indexOfInput)行が無効なタグを再生成していることを伝えているので、同じミスを「修正」して再度試してみる、間違い「修正」それを、見つけたなど

FWIW文字列(これは、C#でですが、コンセプトは翻訳)

public static string RemoveTags(string html, params string[] allowList) 
{ 
    if(html == null) return null; 
    Regex regex = new Regex(@"(?<Tag><(?<TagName>[a-z/]+)\S*?[^<]*?>)", 
          RegexOptions.Compiled | 
          RegexOptions.IgnoreCase | 
          RegexOptions.Multiline); 
    return regex.Replace( 
        html, 
        new MatchEvaluator( 
         new TagMatchEvaluator(allowList).Replace)); 
} 

MatchEvaluatorクラスから不要なHTMLタグを削除し、コードの相続人スニペット

private class TagMatchEvaluator 
{ 
    private readonly ArrayList _allowed = null; 

    public TagMatchEvaluator(string[] allowList) 
    { 
     _allowed = new ArrayList(allowList); 
    } 

    public string Replace(Match match) 
    { 
     if(_allowed.Contains(match.Groups[ "TagName" ].Value)) 
      return match.Value; 
     return ""; 
    } 
} 
+0

mindpiler、heh。 –

0

。あなたはこれを全くテストしましたか?

私は個人的に、このような文字列解析を嫌いです - あなたのエラーがどこにあるかを調べるつもりはありません。デバッガが必要になり、私が入れたいと思っているよりも頭痛が増えます。

1

その他の良い回答に加えて、ちょっとloop invariantsを少し読んでいるかもしれません。あなたのループを終了させるためにチェックする文字列に物を引っ張って戻すことは、あらゆる種類の警鐘を放つべきです。 :)

3

このラインも間違っている:この時点では位置の文字がindexOfInputによって参照ので、常にindexOfInputに等しいindexNextLeftBracket設定することが保証されています

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput) + 1 

は常に、すでに「<」です。

Dim indexNextLeftBracket As Integer = str.IndexOf("<", indexOfInput+1) + 1 

if文に句を追加して、文字列がその式に十分に長いことを確認します。

最後に、他の人がこのコードはあなたがまったく働くことができるなら、このコードは維持する獣と言います。正規表現のように別の解決策を探したり、&lt;ですべて '<'を置き換えても最適です。

+0

+1。よく目撃された! –

関連する問題