为什么 TPath.HasValidPathChars 接受 '?' 作为路径中的有效字符?



为什么System.IOUtils.TPath.HasValidPathChars接受'?'作为路径中的有效字符? 我将第二个参数(使用通配符(设置为 false。因此,根据文档,应该拒绝"?"。尽管如此,该函数仍返回 True 表示 'c:\test\test?\'。

使用通配符 = 指定是否将掩码字符视为 有效的路径字符(例如星号或问号(。

此函数的行为是否仅部分正确?该函数可以返回更好的结果吗?

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。如果ChFInvalidPathChars中,就会发生这种情况。也就是说,如果Ch的序数小于 32,或者是"<>|之一。

您的测试字符串'C:testtest?',实际上这些字符都没有FInvalidPathChars。这意味着if not IsValidPathChar(Ch) then语句中的条件始终计算False。因此,即使您的字符串包含通配符,它也永远无法到达后续测试:

if UseWildcards then

很容易得出结论,无论输入参数UseWildcards的值如何,HasValidPathChars都返回相同的值。如果您对分析有任何疑问,该程序应该可以消除它:

{$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,我的经验是这个单位是不可信的。我不会使用它。找到解决问题的替代方法。

最新更新