[NTOSKRNL]

Fix FsRtlIs*InExpression() by (finally) implementing backtracking.
No regressions noticed regarding kmtest.
Also commented code.

svn path=/trunk/; revision=53859
This commit is contained in:
Pierre Schweitzer 2011-09-26 05:58:13 +00:00
parent d858435e44
commit f5465755dc
2 changed files with 71 additions and 113 deletions

View file

@ -160,7 +160,9 @@ NTAPI
FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
IN PANSI_STRING Name)
{
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, StarFound = MAXUSHORT;
SHORT StarFound = -1;
PUSHORT BackTracking = NULL;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
PAGED_CODE();
ASSERT(Name->Length);
@ -169,74 +171,44 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
while (NamePosition < Name->Length && ExpressionPosition < Expression->Length)
{
/* Basic check to test if chars are equal */
if ((Expression->Buffer[ExpressionPosition] == Name->Buffer[NamePosition]))
{
NamePosition++;
ExpressionPosition++;
}
else if (StarFound != MAXUSHORT && (Expression->Buffer[StarFound + 1] == '*' ||
Expression->Buffer[StarFound + 1] == '?' || Expression->Buffer[StarFound + 1] == ANSI_DOS_DOT))
{
ExpressionPosition = StarFound + 1;
switch (Expression->Buffer[ExpressionPosition])
{
case '*':
StarFound = MAXUSHORT;
break;
case '?':
if (++ExpressionPosition == Expression->Length)
{
NamePosition = Name->Length;
break;
}
MatchingChars = NamePosition;
while (NamePosition < Name->Length &&
Name->Buffer[NamePosition] != Expression->Buffer[ExpressionPosition])
{
NamePosition++;
}
if (NamePosition - MatchingChars > 0)
{
StarFound = MAXUSHORT;
}
break;
case ANSI_DOS_DOT:
while (NamePosition < Name->Length && Name->Buffer[NamePosition] != '.')
{
NamePosition++;
}
ExpressionPosition++;
StarFound = MAXUSHORT;
break;
default:
/* Should never happen */
ASSERT(FALSE);
}
}
/* Check cases that eat one char */
else if ((Expression->Buffer[ExpressionPosition] == '?') || (Expression->Buffer[ExpressionPosition] == ANSI_DOS_QM) ||
(Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT && Name->Buffer[NamePosition] == '.'))
{
NamePosition++;
ExpressionPosition++;
StarFound = MAXUSHORT;
}
/* Test star */
else if (Expression->Buffer[ExpressionPosition] == '*')
{
StarFound = ExpressionPosition++;
/* 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;
}
else if (Expression->Buffer[ExpressionPosition] != '?')
{
NamePosition++;
}
}
/* Check DOS_STAR */
else if (Expression->Buffer[ExpressionPosition] == ANSI_DOS_STAR)
{
StarFound = MAXUSHORT;
MatchingChars = NamePosition;
while (MatchingChars < Name->Length)
{
@ -248,19 +220,24 @@ FsRtlIsDbcsInExpression(IN PANSI_STRING Expression,
}
ExpressionPosition++;
}
else if (StarFound != MAXUSHORT)
/* If nothing match, try to backtrack */
else if (StarFound >= 0)
{
ExpressionPosition = StarFound + 1;
while (NamePosition < Name->Length &&
Name->Buffer[NamePosition] != Expression->Buffer[ExpressionPosition])
{
NamePosition++;
}
ExpressionPosition = BackTracking[StarFound--];
}
/* 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 (ExpressionPosition + 1 == Expression->Length && NamePosition == Name->Length &&
Expression->Buffer[ExpressionPosition] == ANSI_DOS_DOT)

View file

@ -23,8 +23,10 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
IN BOOLEAN IgnoreCase,
IN PWCHAR UpcaseTable OPTIONAL)
{
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, StarFound = MAXUSHORT;
SHORT StarFound = -1;
PUSHORT BackTracking = NULL;
UNICODE_STRING IntExpression;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
PAGED_CODE();
/* Check if we were given strings at all */
@ -99,76 +101,45 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
while (NamePosition < Name->Length / sizeof(WCHAR) && ExpressionPosition < Expression->Length / sizeof(WCHAR))
{
/* Basic check to test if chars are equal */
if ((Expression->Buffer[ExpressionPosition] == (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition])))
{
NamePosition++;
ExpressionPosition++;
}
else if (StarFound != MAXUSHORT && (Expression->Buffer[StarFound + 1] == L'*' ||
Expression->Buffer[StarFound + 1] == L'?' || Expression->Buffer[StarFound + 1] == DOS_DOT))
{
ExpressionPosition = StarFound + 1;
switch (Expression->Buffer[ExpressionPosition])
{
case L'*':
StarFound = MAXUSHORT;
break;
case L'?':
if (++ExpressionPosition == Expression->Length / sizeof(WCHAR))
{
NamePosition = Name->Length / sizeof(WCHAR);
break;
}
MatchingChars = NamePosition;
while (NamePosition < Name->Length / sizeof(WCHAR) &&
(IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition])
{
NamePosition++;
}
if (NamePosition - MatchingChars > 0)
{
StarFound = MAXUSHORT;
}
break;
case DOS_DOT:
while (NamePosition < Name->Length / sizeof(WCHAR) &&
Name->Buffer[NamePosition] != L'.')
{
NamePosition++;
}
ExpressionPosition++;
StarFound = MAXUSHORT;
break;
default:
/* Should never happen */
ASSERT(FALSE);
}
}
/* Check cases that eat one char */
else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
(Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
{
NamePosition++;
ExpressionPosition++;
StarFound = MAXUSHORT;
}
/* Test star */
else if (Expression->Buffer[ExpressionPosition] == L'*')
{
StarFound = ExpressionPosition++;
/* Save star position */
if (!BackTracking)
{
BackTracking = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,
(Expression->Length / sizeof(WCHAR)) * sizeof(USHORT),
'nrSF');
}
BackTracking[++StarFound] = ExpressionPosition++;
/* If star is at the end, then eat all rest and leave */
if (ExpressionPosition == Expression->Length / sizeof(WCHAR))
{
NamePosition = Name->Length / sizeof(WCHAR);
break;
}
else if (Expression->Buffer[ExpressionPosition] != L'?')
{
NamePosition++;
}
}
/* Check DOS_STAR */
else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
{
StarFound = MAXUSHORT;
MatchingChars = NamePosition;
while (MatchingChars < Name->Length / sizeof(WCHAR))
{
@ -180,20 +151,25 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
}
ExpressionPosition++;
}
else if (StarFound != MAXUSHORT)
/* If nothing match, try to backtrack */
else if (StarFound >= 0)
{
ExpressionPosition = StarFound + 1;
while (NamePosition < Name->Length / sizeof(WCHAR) &&
(IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition])
{
NamePosition++;
}
ExpressionPosition = BackTracking[StarFound--];
}
/* Otherwise, fail */
else
{
break;
}
/* Under certain circumstances, expression is over, but name isn't
* and we can backtrack, then, backtrack */
if (ExpressionPosition == Expression->Length / sizeof(WCHAR) &&
NamePosition != Name->Length / sizeof(WCHAR) &&
StarFound >= 0)
{
ExpressionPosition = BackTracking[StarFound--];
}
}
if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
Expression->Buffer[ExpressionPosition] == DOS_DOT)
@ -201,6 +177,11 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
ExpressionPosition++;
}
if (BackTracking)
{
ExFreePoolWithTag(BackTracking, 'nrSF');
}
return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
}