为什么 TPath.HasValidPathChars 接受 '?'作为路径中的有效字符?
Why does TPath.HasValidPathChars accept '?' as a valid char in a path?
为什么 System.IOUtils.TPath.HasValidPathChars 接受'?'作为路径中的有效字符?
我将第二个参数 (UseWildcards) 设置为 false。因此,根据文档,'?'应该被拒绝。不过,函数 returns 对 'c:\test\test?\' 为真。
UseWildcards = Specifies whether the mask characters are treated as
valid path characters (e.g. asterisk or question mark).
这个函数的行为是否只是部分正确?该函数是否可以返回更好的结果?
TPath.HasValidPathChars
彻底坏掉了。这是它的实现:
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;
关键点是对IsValidPathChar
的调用。让我们看看它的作用。
class function TPath.IsValidPathChar(const AChar: Char): Boolean;
begin
Result := not IsCharInOrderedArray(AChar, FInvalidPathChars);
end;
现在,FInvalidPathChars
定义为:
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;
即所有小于32的序数,以及"
、<
、>
和|
.
我们还需要了解 IsPathWildcardChar
的作用。
class function TPath.IsPathWildcardChar(const AChar: Char): Boolean;
begin
Result := IsCharInOrderedArray(AChar, FPathWildcardChars);
end;
其中 FPathWildcardChars
是:
FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE;
现在,回到 TPath.HasValidPathChars
。让我们考虑这个 if
语句:
if not IsValidPathChar(Ch) then
当 IsValidPathChar(Ch)
为 False
时,条件 not IsValidPathChar(Ch)
的计算结果为 True
。如果 Ch
在 FInvalidPathChars
中,就会发生这种情况。也就是说,如果 Ch
的序数小于 32,或者是 "
、<
、>
和 |
.
之一
您的测试字符串是 'C:\test\test?\'
,实际上 none 这些字符在 FInvalidPathChars
中。这意味着 if not IsValidPathChar(Ch) then
语句中的条件总是计算 False
。所以即使你的字符串包含通配符,它也永远无法到达后续测试:
if UseWildcards then
不考虑输入参数UseWildcards
的值,很容易得出HasValidPathChars
returns相同的值。如果你对分析有任何疑问,这个程序应该打消它:
{$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.
这看起来像是这个可怕的 IOUtils
单元中的另一个功能,但未正确实施且未经过测试。
我已提交错误报告:RSP-18696。
根据 IOUtils
偶然发现的许多此类问题,我的经验是该单位不值得信任。我不会使用它。找到解决问题的替代方法。
为什么 System.IOUtils.TPath.HasValidPathChars 接受'?'作为路径中的有效字符? 我将第二个参数 (UseWildcards) 设置为 false。因此,根据文档,'?'应该被拒绝。不过,函数 returns 对 'c:\test\test?\' 为真。
UseWildcards = Specifies whether the mask characters are treated as valid path characters (e.g. asterisk or question mark).
这个函数的行为是否只是部分正确?该函数是否可以返回更好的结果?
TPath.HasValidPathChars
彻底坏掉了。这是它的实现:
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;
关键点是对IsValidPathChar
的调用。让我们看看它的作用。
class function TPath.IsValidPathChar(const AChar: Char): Boolean;
begin
Result := not IsCharInOrderedArray(AChar, FInvalidPathChars);
end;
现在,FInvalidPathChars
定义为:
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;
即所有小于32的序数,以及"
、<
、>
和|
.
我们还需要了解 IsPathWildcardChar
的作用。
class function TPath.IsPathWildcardChar(const AChar: Char): Boolean;
begin
Result := IsCharInOrderedArray(AChar, FPathWildcardChars);
end;
其中 FPathWildcardChars
是:
FPathWildcardChars := TCharArray.Create('*', '/', ':', '?', '\'); // DO NOT LOCALIZE;
现在,回到 TPath.HasValidPathChars
。让我们考虑这个 if
语句:
if not IsValidPathChar(Ch) then
当 IsValidPathChar(Ch)
为 False
时,条件 not IsValidPathChar(Ch)
的计算结果为 True
。如果 Ch
在 FInvalidPathChars
中,就会发生这种情况。也就是说,如果 Ch
的序数小于 32,或者是 "
、<
、>
和 |
.
您的测试字符串是 'C:\test\test?\'
,实际上 none 这些字符在 FInvalidPathChars
中。这意味着 if not IsValidPathChar(Ch) then
语句中的条件总是计算 False
。所以即使你的字符串包含通配符,它也永远无法到达后续测试:
if UseWildcards then
不考虑输入参数UseWildcards
的值,很容易得出HasValidPathChars
returns相同的值。如果你对分析有任何疑问,这个程序应该打消它:
{$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.
这看起来像是这个可怕的 IOUtils
单元中的另一个功能,但未正确实施且未经过测试。
我已提交错误报告:RSP-18696。
根据 IOUtils
偶然发现的许多此类问题,我的经验是该单位不值得信任。我不会使用它。找到解决问题的替代方法。