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

View file

@ -23,8 +23,10 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
IN BOOLEAN IgnoreCase, IN BOOLEAN IgnoreCase,
IN PWCHAR UpcaseTable OPTIONAL) IN PWCHAR UpcaseTable OPTIONAL)
{ {
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars, StarFound = MAXUSHORT; SHORT StarFound = -1;
PUSHORT BackTracking = NULL;
UNICODE_STRING IntExpression; UNICODE_STRING IntExpression;
USHORT ExpressionPosition = 0, NamePosition = 0, MatchingChars;
PAGED_CODE(); PAGED_CODE();
/* Check if we were given strings at all */ /* 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)) 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]))) if ((Expression->Buffer[ExpressionPosition] == (IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] : Name->Buffer[NamePosition])))
{ {
NamePosition++; NamePosition++;
ExpressionPosition++; ExpressionPosition++;
} }
else if (StarFound != MAXUSHORT && (Expression->Buffer[StarFound + 1] == L'*' || /* Check cases that eat one char */
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);
}
}
else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) || else if (Expression->Buffer[ExpressionPosition] == L'?' || (Expression->Buffer[ExpressionPosition] == DOS_QM) ||
(Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.')) (Expression->Buffer[ExpressionPosition] == DOS_DOT && Name->Buffer[NamePosition] == L'.'))
{ {
NamePosition++; NamePosition++;
ExpressionPosition++; ExpressionPosition++;
StarFound = MAXUSHORT;
} }
/* Test star */
else if (Expression->Buffer[ExpressionPosition] == L'*') 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)) if (ExpressionPosition == Expression->Length / sizeof(WCHAR))
{ {
NamePosition = Name->Length / sizeof(WCHAR); NamePosition = Name->Length / sizeof(WCHAR);
break; break;
} }
else if (Expression->Buffer[ExpressionPosition] != L'?')
{
NamePosition++;
}
} }
/* Check DOS_STAR */
else if (Expression->Buffer[ExpressionPosition] == DOS_STAR) else if (Expression->Buffer[ExpressionPosition] == DOS_STAR)
{ {
StarFound = MAXUSHORT;
MatchingChars = NamePosition; MatchingChars = NamePosition;
while (MatchingChars < Name->Length / sizeof(WCHAR)) while (MatchingChars < Name->Length / sizeof(WCHAR))
{ {
@ -180,20 +151,25 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
} }
ExpressionPosition++; ExpressionPosition++;
} }
else if (StarFound != MAXUSHORT) /* If nothing match, try to backtrack */
else if (StarFound >= 0)
{ {
ExpressionPosition = StarFound + 1; ExpressionPosition = BackTracking[StarFound--];
while (NamePosition < Name->Length / sizeof(WCHAR) &&
(IgnoreCase ? UpcaseTable[Name->Buffer[NamePosition]] :
Name->Buffer[NamePosition]) != Expression->Buffer[ExpressionPosition])
{
NamePosition++;
}
} }
/* Otherwise, fail */
else else
{ {
break; 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) && if (ExpressionPosition + 1 == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR) &&
Expression->Buffer[ExpressionPosition] == DOS_DOT) Expression->Buffer[ExpressionPosition] == DOS_DOT)
@ -201,6 +177,11 @@ FsRtlIsNameInExpressionPrivate(IN PUNICODE_STRING Expression,
ExpressionPosition++; ExpressionPosition++;
} }
if (BackTracking)
{
ExFreePoolWithTag(BackTracking, 'nrSF');
}
return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR)); return (ExpressionPosition == Expression->Length / sizeof(WCHAR) && NamePosition == Name->Length / sizeof(WCHAR));
} }