TPath.HasValidPathChars
jest całkowicie zepsuty. To jest jego realizacja:
class function TPath.HasValidPathChars(const Path: string;
const UseWildcards: Boolean): Boolean;
var
PPath: PChar;
PathLen: Integer;
Ch: Char;
I: Integer;
begin
// Result will become True if an invalid path char is found
{$IFDEF MSWINDOWS}
I := GetPosAfterExtendedPrefix(Path) - 1;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
I := 0;
{$ENDIF POSIX}
PPath := PChar(Path);
PathLen := Length(Path);
Result := False;
while (not Result) and (i < PathLen) do
begin
Ch := PPath[i];
if not IsValidPathChar(Ch) then
if UseWildcards then
if not IsPathWildcardChar(Ch) then
Result := True
else
Inc(i)
else
Result := True
else
Inc(i);
end;
Result := not Result;
end;
Kluczowym punktem jest wywołanie IsValidPathChar
. Spójrzmy, co to oznacza.
class function TPath.IsValidPathChar(const AChar: Char): Boolean;
begin
Result := not IsCharInOrderedArray(AChar, FInvalidPathChars);
end;
Teraz FInvalidPathChars
określa się:
FInvalidPathChars := TCharArray.Create(
#0, #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12,
#13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24,
#25, #26, #27, #28, #29, #30, #31,
'"', '<', '>', '|'); // DO NOT LOCALIZE;
Oznacza to, że wszystkie porządkowe mniej niż 32, a "
, <
, >
i |
.
Musimy również zrozumieć, co robi IsPathWildcardChar
.
class function TPath.IsPathWildcardChar(const AChar: Char): Boolean;
begin
Result := IsCharInOrderedArray(AChar, FPathWildcardChars);
end;
Gdzie FPathWildcardChars
jest:
FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE;
Wróćmy teraz do TPath.HasValidPathChars
. Rozważmy ten if
oświadczenie:
if not IsValidPathChar(Ch) then
Warunkiem not IsValidPathChar(Ch)
ocenia się True
gdy IsValidPathChar(Ch)
jest False
. Co się stanie, jeśli Ch
jest w FInvalidPathChars
. To znaczy, jeśli Ch
ma liczbę porządkową mniejszą niż 32, lub jest jedną z "
, <
, >
i |
.
Twój ciąg testowy to 'C:\test\test?\'
i w rzeczywistości żaden z tych znaków nie jest w FInvalidPathChars
. Co oznacza, że warunek w instrukcji if not IsValidPathChar(Ch) then
zawsze ocenia False
. Więc nawet jeśli ciąg zawiera wieloznaczny, to nigdy nie może dotrzeć do kolejnego testu:
if UseWildcards then
łatwo jest stwierdzić, że HasValidPathChars
zwraca taką samą wartość niezależnie od wartości parametru wejściowego UseWildcards
. A jeśli masz jakiekolwiek wątpliwości co do analizy, program ten powinien je rozwiać:
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.IOUtils;
procedure Main;
var
Ch: Char;
begin
for Ch := low(Ch) to high(Ch) do
if TPath.HasValidPathChars(Ch, False)<>TPath.HasValidPathChars(Ch, True) then
Writeln('different at #' + IntToStr(ord(Ch)));
Writeln('finished');
end;
begin
Main;
Readln;
end.
To wygląda jeszcze inną funkcję w tym bał IOUtils
jednostki, które zostały niewłaściwie wykonane i nie testowane.
Złożyłem zgłoszenie błędu: RSP-18696.
Na podstawie natknięcia się na wiele takich problemów z IOUtils
, moim doświadczeniem jest to, że jednostka nie jest zaufana. Nie użyłbym tego. Znajdź alternatywny sposób rozwiązania problemu.
Znaku?? Nie należy odrzucać, ponieważ ścieżki mogą zawierać znaki zapytania w systemie Windows. Przykład: https://superuser.com/q/1069055 –
Ten post użytkownika superużytkownicy również stwierdza: "Nie można używać tego rodzaju ścieżek w celu uzyskania dostępu do plików lub katalogów w przestrzeni użytkownika. Tylko niektóre komponenty systemowe niskiego poziomu są zaprojektowane do pracy z Ścieżki Menedżera obiektów. " Z tego punktu widzenia '?' Jest nieprawidłową ścieżką. – gabr
@ GünthertheBeautiful - Artykuł mówi, że \ ?? jest poprawną ścieżką, więc HasValidPathChars powinno sprawdzić "??" i zwraca true, jeśli poprawny wzorzec (\ ??) zostanie znaleziony, a false, gdy istnieje pojedynczy znak "?" – Ampere