Manchmal will man Code analysieren - zB Sql auf unerwünschte Schlüsselworte - siehe: Gegen SqlInjection
Da stösst man auf das Problem der Quotes, nämlich gequotetes ist ja (in jeder Sprache) syntaktisch ein irrelevanter Block.
Unsere Code-Analyse darf also keinesfalls QuotedBlocks mit-analysieren - es käme zu falschen Ergebnissen.
Zunächstmal sieht das einfach aus - Beispiel: Man kann ja einfach am
Allerdings kennt Sql mehrere Quote-Marks, zB gibts auch
Oder wir splitten nach beidem:
Etwas wie dieses ist ja als quote-syntaktisch falsch abzulehnen:Andererseits dieses hier:ist syntaktisch korrekt: Ein Quote-Block kann Quote-Marks anderer Art(en) einschliessen (und somit syntaktisch deaktivieren).
Das ist interessant, denn ein Quote wegnehmen erzeugt u.U. einen anderen, neuen Quote-Block:Da fragt sich doch der Split-Algo: Warum zum Kuckuck lautet der Quote-Block nun genau:
Antwort: Es gilt Leserichtung von links nach rechts, und der erste auftretende Quote gewinnt.
Pfui! - Leserichtung!
Aber Regex kann - Regex liest standardmässig von links nach rechts.
Also hab ich nun diesen Regex-Trick erfunden, um den's hier geht:
Der Regex-Pattern erkennt sowohl Single- als auch Double-Quote-Blocks. Im Replace ersetzt er sie durch sich selbst - also ersetzt er sie gar nicht.
Sondern er fügt davor und danach ein Marker-Zeichen ein.
Anschliessend wird an den Markern gesplittet, und wir erhalten das Sql wunderbar zerteilt als Array, bei dem jedes zweite Element gequoted ist:
Beachte Ausgabe
So, wir können nun also sicher Quote-Blocks identifizieren - ja, es ist nun sogar möglich, Quote-Syntaxfehler auszumachen, also nicht-geschlossene Quote-Blocks!
Nämlich wenn ein öffnendes Quote-Mark in einem unquoted-Segment auftritt:
"Öffnendes Quote-Mark"?? Quote-Marks sind doch jeweils gleich, also vorne wie hinten
Tja, aber zB Sql kennt auch diese QuoteMarks:
Und auch Kommentare zählen zu den Quotes - weil gelten dieselben Regeln:
Leserichtung links->rechts, und ein Comment kann ein QuoteMark auskommentieren, ein Quote kann aber auch ein Kommentar-Zeichen quoten:
Tja - doof: Der Vbp-Syntax-Highlighter kriegts in der letzten Zeile leider nicht hin,
Hier zum Beweis der Syntax noch Bildle vom SqlServer:
Jedenfalls für Sql würde der Quote-Regex-pattern aller Quotes so lauten:
Noch Bemerkung zur angehängten Sample-App: Es ist eine Konsole-Anwendung, die Ausgabe erfolgt aber via Debug.Print.
Daher rauscht das Ding einfach durch, und das Ergebnis kann man im Output-Fenster des VisualStudios angucken (als Debug kompilieren).
Da stösst man auf das Problem der Quotes, nämlich gequotetes ist ja (in jeder Sprache) syntaktisch ein irrelevanter Block.
Unsere Code-Analyse darf also keinesfalls QuotedBlocks mit-analysieren - es käme zu falschen Ergebnissen.
Zunächstmal sieht das einfach aus - Beispiel: Man kann ja einfach am
"
splitten, und verarbeitet nur jedes zweite StringSegment.Allerdings kennt Sql mehrere Quote-Marks, zB gibts auch
'
- was machen wir also mit dem hier? Da wirds ungemütlich - wir müssen erst nach "
splitten, und das gesplittete, was noch verarbeitet wird nach '
splitten.Oder wir splitten nach beidem:
"'
, müssen aber aufpassen, dass beim jeweiligen Segment der Start-Quote mit dem End-Quote übereinstimmt.Etwas wie dieses ist ja als quote-syntaktisch falsch abzulehnen:Andererseits dieses hier:ist syntaktisch korrekt: Ein Quote-Block kann Quote-Marks anderer Art(en) einschliessen (und somit syntaktisch deaktivieren).
Das ist interessant, denn ein Quote wegnehmen erzeugt u.U. einen anderen, neuen Quote-Block:Da fragt sich doch der Split-Algo: Warum zum Kuckuck lautet der Quote-Block nun genau:
' ate" OR a = '
, und nicht: " OR a = 'Ins "
oder: 'Ins " ert'
?Antwort: Es gilt Leserichtung von links nach rechts, und der erste auftretende Quote gewinnt.
Pfui! - Leserichtung!
Split()
ist draussen - kannenet Aber Regex kann - Regex liest standardmässig von links nach rechts.
Also hab ich nun diesen Regex-Trick erfunden, um den's hier geht:
VB.NET-Quellcode
Sondern er fügt davor und danach ein Marker-Zeichen ein.
Anschliessend wird an den Markern gesplittet, und wir erhalten das Sql wunderbar zerteilt als Array, bei dem jedes zweite Element gequoted ist:
4
: Wenn der Input auf einem Quote-Mark endet, folgt trotzdem noch ein unquoted Segment - ist dann halt leer.So, wir können nun also sicher Quote-Blocks identifizieren - ja, es ist nun sogar möglich, Quote-Syntaxfehler auszumachen, also nicht-geschlossene Quote-Blocks!
Nämlich wenn ein öffnendes Quote-Mark in einem unquoted-Segment auftritt:
VB.NET-Quellcode
- Private _rgxQuotes As New Regex("'.*?'|"".*?""", RegexOptions.Singleline)
- Private _OpenQuoteMarks As List(Of String) = GetOpenQuoteMarks()
- Private _marker As Char = Convert.ToChar(&HF018) ' ein Zeichen, dass nie vorkommt
- Private Function GetOpenQuoteMarks() As List(Of String)
- Dim pattern = Regex.Unescape(_rgxQuotes.ToString)
- Return (From p In pattern.Split("|"c) Select p.Split("."c)(0)).ToList
- End Function
- Public Function SplitQuotes(s As String) As String()
- Dim splts = _rgxQuotes.Replace(s, $"{_marker}$0{_marker}").Split(_marker)
- For i = 0 To splts.Length - 1 Step 2
- Dim splt = splts(i)
- If _OpenQuoteMarks.Any(Function(x) splt.Contains(x)) Then
- Throw New InvalidOperationException("unclosed quote-mark detected")
- End If
- Next
- Return splts
- End Function
"Öffnendes Quote-Mark"?? Quote-Marks sind doch jeweils gleich, also vorne wie hinten
"
, oder '
!Tja, aber zB Sql kennt auch diese QuoteMarks:
[]
(und der Vollständigkeit halber diesen auch noch: `
)Und auch Kommentare zählen zu den Quotes - weil gelten dieselben Regeln:
Leserichtung links->rechts, und ein Comment kann ein QuoteMark auskommentieren, ein Quote kann aber auch ein Kommentar-Zeichen quoten:
[]
-gequotetes korrekt darzustellen Hier zum Beweis der Syntax noch Bildle vom SqlServer:
Jedenfalls für Sql würde der Quote-Regex-pattern aller Quotes so lauten:
'.*?'|`.*?`|\[.*?]|"".*?""|/\*.*?\*/|--.*?\n
Noch Bemerkung zur angehängten Sample-App: Es ist eine Konsole-Anwendung, die Ausgabe erfolgt aber via Debug.Print.
Daher rauscht das Ding einfach durch, und das Ergebnis kann man im Output-Fenster des VisualStudios angucken (als Debug kompilieren).
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()