From: Dmitry Chapyshev Date: Wed, 28 Sep 2016 19:01:10 +0000 (+0000) Subject: [NTOS:FSRTL] Rework FsRtlIsDbcsInExpression for correct parsing some expressions X-Git-Tag: ReactOS-0.4.3~216 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=d507b7555e708d89a1c27aa99c839519179220b2 [NTOS:FSRTL] Rework FsRtlIsDbcsInExpression for correct parsing some expressions * Fixes 1 test for kmtest:FsRtlExpression svn path=/trunk/; revision=72839 --- diff --git a/reactos/ntoskrnl/fsrtl/dbcsname.c b/reactos/ntoskrnl/fsrtl/dbcsname.c index 8ecd3b4593a..ccaaa9b37c6 100644 --- a/reactos/ntoskrnl/fsrtl/dbcsname.c +++ b/reactos/ntoskrnl/fsrtl/dbcsname.c @@ -160,9 +160,14 @@ NTAPI FsRtlIsDbcsInExpression(IN PANSI_STRING Expression, IN PANSI_STRING Name) { - SHORT StarFound = -1, DosStarFound = -1; - PUSHORT BackTracking = NULL, DosBackTracking = NULL; - USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, LastDot; + USHORT Offset, Position, BackTrackingPosition, OldBackTrackingPosition; + USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0}; + PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer; + USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1; + USHORT NameChar = 0, ExpressionChar; + BOOLEAN EndOfName = FALSE; + BOOLEAN Result; + BOOLEAN DontSkipDot; PAGED_CODE(); ASSERT(Name->Length); @@ -232,170 +237,180 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression, } } - while (NamePosition < Name->Length && ExpressionPosition < Expression->Length) + /* Name parsing loop */ + for (; !EndOfName; MatchingChars = BackTrackingPosition) { - /* Basic check to test if chars are equal */ - if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition])) - { - NamePosition++; - ExpressionPosition++; - } - /* Check cases that eat one char */ - else if (Expression->Buffer[ExpressionPosition] == '?') + /* Reset positions */ + OldBackTrackingPosition = BackTrackingPosition = 0; + + if (NamePosition >= Name->Length) { - NamePosition++; - ExpressionPosition++; + EndOfName = TRUE; + if (OldBackTracking[MatchingChars - 1] == Expression->Length * 2) + break; } - /* Test star */ - else if (Expression->Buffer[ExpressionPosition] == '*') + else { - /* Skip contigous stars */ - while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == '*') + /* If lead byte present */ + if (FsRtlIsLeadDbcsCharacter(Name->Buffer[NamePosition])) { - ExpressionPosition++; + NameChar = Name->Buffer[NamePosition] + + (0x100 * Name->Buffer[NamePosition + 1]); + NamePosition += sizeof(USHORT); } - - /* Save star position */ - if (!BackTracking) - { - BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, - Expression->Length * sizeof(USHORT), 'nrSF'); - } - BackTracking[++StarFound] = ExpressionPosition++; - - /* If star is at the end, then eat all rest and leave */ - if (ExpressionPosition == Expression->Length) - { - NamePosition = Name->Length; - break; - } - /* Allow null matching */ - else if (Expression->Buffer[ExpressionPosition] != '?' && - Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition]) + else { - NamePosition++; + NameChar = Name->Buffer[NamePosition]; + NamePosition += sizeof(UCHAR); } } - /* Check DOS_STAR */ - else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR) + + while (MatchingChars > OldBackTrackingPosition) { - /* Skip contigous stars */ - while (ExpressionPosition + 1 < Expression->Length && Expression->Buffer[ExpressionPosition + 1] == ANSI_DOS_STAR) - { - ExpressionPosition++; - } + ExpressionPosition = (OldBackTracking[OldBackTrackingPosition++] + 1) / 2; - /* Look for last dot */ - MatchingChars = 0; - LastDot = (USHORT)-1; - while (MatchingChars < Name->Length) + /* Expression parsing loop */ + for (Offset = 0; ExpressionPosition < Expression->Length; ) { - if (Name->Buffer[MatchingChars] == '.') + ExpressionPosition += Offset; + + if (ExpressionPosition == Expression->Length) { - LastDot = MatchingChars; - if (LastDot > NamePosition) - break; + BackTracking[BackTrackingPosition++] = Expression->Length * 2; + break; } - MatchingChars++; - } + /* If buffer too small */ + if (BackTrackingPosition > RTL_NUMBER_OF(BackTrackingBuffer) - 1) + { + /* Allocate memory for BackTracking */ + BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, + (Expression->Length + 1) * sizeof(USHORT) * 2, + 'nrSF'); + /* Copy old buffer content */ + RtlCopyMemory(BackTracking, + BackTrackingBuffer, + RTL_NUMBER_OF(BackTrackingBuffer) * sizeof(USHORT)); + + /* Allocate memory for OldBackTracking */ + OldBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, + (Expression->Length + 1) * sizeof(USHORT) * 2, + 'nrSF'); + /* Copy old buffer content */ + RtlCopyMemory(OldBackTracking, + OldBackTrackingBuffer, + RTL_NUMBER_OF(OldBackTrackingBuffer) * sizeof(USHORT)); + } - /* If we don't have dots or we didn't find last yet - * start eating everything - */ - if (MatchingChars != Name->Length || LastDot == (USHORT)-1) - { - if (!DosBackTracking) DosBackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, - Expression->Length * sizeof(USHORT), 'nrSF'); - DosBackTracking[++DosStarFound] = ExpressionPosition++; + /* If lead byte present */ + if (FsRtlIsLeadDbcsCharacter(Expression->Buffer[ExpressionPosition])) + { + ExpressionChar = Expression->Buffer[ExpressionPosition] + + (0x100 * Expression->Buffer[ExpressionPosition + 1]); + Offset = sizeof(USHORT); + } + else + { + ExpressionChar = Expression->Buffer[ExpressionPosition]; + Offset = sizeof(UCHAR); + } - /* Not the same char, start exploring */ - if (Expression->Buffer[ExpressionPosition] != Name->Buffer[NamePosition]) - NamePosition++; - } - else - { - /* Else, if we are at last dot, eat it - otherwise, null match */ - if (Name->Buffer[NamePosition] == '.') - NamePosition++; + /* Basic check to test if chars are equal */ + if (ExpressionChar == NameChar && !EndOfName) + { + BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2; + } + /* Check cases that eat one char */ + else if (ExpressionChar == '?' && !EndOfName) + { + BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2; + } + /* Test star */ + else if (ExpressionChar == '*') + { + BackTracking[BackTrackingPosition++] = ExpressionPosition * 2; + BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1; + continue; + } + /* Check DOS_STAR */ + else if (ExpressionChar == ANSI_DOS_STAR) + { + /* Look for last dot */ + DontSkipDot = TRUE; + if (!EndOfName && NameChar == '.') + { + for (Position = NamePosition; Position < Name->Length; ) + { + /* If lead byte not present */ + if (!FsRtlIsLeadDbcsCharacter(Name->Buffer[Position])) + { + if (Name->Buffer[Position] == '.') + { + DontSkipDot = FALSE; + break; + } + + Position += sizeof(UCHAR); + } + else + { + Position += sizeof(USHORT); + } + } + } + + if (EndOfName || NameChar != '.' || !DontSkipDot) + BackTracking[BackTrackingPosition++] = ExpressionPosition * 2; + + BackTracking[BackTrackingPosition++] = (ExpressionPosition * 2) + 1; + continue; + } + /* Check DOS_DOT */ + else if (ExpressionChar == DOS_DOT) + { + if (EndOfName) continue; - ExpressionPosition++; - } - } - /* Check DOS_DOT */ - else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT) - { - /* We only match dots */ - if (Name->Buffer[NamePosition] == '.') - { - NamePosition++; - } - /* Try to explore later on for null matching */ - else if (ExpressionPosition + 1 < Expression->Length && - Name->Buffer[NamePosition] == Expression->Buffer[ExpressionPosition + 1]) - { - NamePosition++; - } - ExpressionPosition++; - } - /* Check DOS_QM */ - else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM) - { - /* We match everything except dots */ - if (Name->Buffer[NamePosition] != '.') - { - NamePosition++; + if (NameChar == '.') + BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2; + } + /* Check DOS_QM */ + else if (ExpressionChar == ANSI_DOS_QM) + { + if (EndOfName || NameChar == '.') continue; + + BackTracking[BackTrackingPosition++] = (ExpressionPosition + Offset) * 2; + } + + /* Leave from loop */ + break; } - ExpressionPosition++; - } - /* If nothing match, try to backtrack */ - else if (StarFound >= 0) - { - ExpressionPosition = BackTracking[StarFound--]; - } - else if (DosStarFound >= 0) - { - ExpressionPosition = DosBackTracking[DosStarFound--]; - } - /* Otherwise, fail */ - else - { - break; - } - /* Under certain circumstances, expression is over, but name isn't - * and we can backtrack, then, backtrack */ - if (ExpressionPosition == Expression->Length && - NamePosition != Name->Length && StarFound >= 0) - { - ExpressionPosition = BackTracking[StarFound--]; - } - } - /* If we have nullable matching wc at the end of the string, eat them */ - if (ExpressionPosition != Expression->Length && NamePosition == Name->Length) - { - while (ExpressionPosition < Expression->Length) - { - if (Expression->Buffer[ExpressionPosition] != ANSI_DOS_DOT && - Expression->Buffer[ExpressionPosition] != '*' && - Expression->Buffer[ExpressionPosition] != ANSI_DOS_STAR) + for (Position = 0; MatchingChars > OldBackTrackingPosition && Position < BackTrackingPosition; Position++) { - break; + while (MatchingChars > OldBackTrackingPosition && + BackTracking[Position] > OldBackTracking[OldBackTrackingPosition]) + { + ++OldBackTrackingPosition; + } } - ExpressionPosition++; } + + /* Swap pointers */ + BackTrackingSwap = BackTracking; + BackTracking = OldBackTracking; + OldBackTracking = BackTrackingSwap; } - if (BackTracking) - { + /* Store result value */ + Result = (OldBackTracking[MatchingChars - 1] == Expression->Length * 2); + + /* Frees the memory if necessary */ + if (BackTracking != BackTrackingBuffer && BackTracking != OldBackTrackingBuffer) ExFreePoolWithTag(BackTracking, 'nrSF'); - } - if (DosBackTracking) - { - ExFreePoolWithTag(DosBackTracking, 'nrSF'); - } + if (OldBackTracking != BackTrackingBuffer && OldBackTracking != OldBackTrackingBuffer) + ExFreePoolWithTag(OldBackTracking, 'nrSF'); - return (ExpressionPosition == Expression->Length && NamePosition == Name->Length); + return Result; } /*++ diff --git a/reactos/ntoskrnl/fsrtl/name.c b/reactos/ntoskrnl/fsrtl/name.c index 38304547ee8..f470cc034de 100644 --- a/reactos/ntoskrnl/fsrtl/name.c +++ b/reactos/ntoskrnl/fsrtl/name.c @@ -27,9 +27,9 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression, USHORT BackTrackingBuffer[16], OldBackTrackingBuffer[16] = {0}; PUSHORT BackTrackingSwap, BackTracking = BackTrackingBuffer, OldBackTracking = OldBackTrackingBuffer; UNICODE_STRING IntExpression; - USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars = 1; + USHORT ExpressionPosition, NamePosition = 0, MatchingChars = 1; BOOLEAN EndOfName = FALSE; - BOOLEAN Result = FALSE; + BOOLEAN Result; BOOLEAN DontSkipDot; WCHAR CompareChar; PAGED_CODE();