【问题标题】:Delphi TPath.GetTempPath result is croppedDelphi TPath.GetTempPath 结果被裁剪
【发布时间】:2010-08-09 13:30:49
【问题描述】:

我正在使用 Delphi 2010,我的程序想要获取系统的临时路径。我正在使用 TPath.GetTempPath 并且一切正常……至少对我和我的同事来说。但在某些客户机器上,此方法返回(当然)不存在的裁剪路径。我发现问题似乎是对 GetLongPathName() 的底层调用的结果。

完整的代码如下所示:

[...]
var
 TmpDir : String;
 Len : Integer;
begin

 [... Call to GetTempPath succeeds and we have a valid temp directory in short "~" notation in var TmpDir ...]

 Len := GetLongPathName(PChar(TmpDir), nil, 0);      // Len = 37
    SetLength(TmpDir, Len - 1);                         // We want to set the len of TmpDir to 37 - 1.
    GetLongPathName(PChar(TmpDir), PChar(TmpDir), Len); // Only 32 (instead of 36) characters are copied - so we have a cropped path - But why?!

end;
[...]

这只发生在某些系统上,我不知道为什么。我找到了一个讨厌的解决方法,但我想知道这里发生了什么。

有人可以解释一下吗?

【问题讨论】:

  • 您能给我们提供正确(预期)和错误(实际)路径名的示例吗?可能是 Unicode 或编码问题?
  • 我们最初也是这么认为的,但是路径名不包含任何可能导致 Unicode 转换问题的字符。 GetLongPathName 的结果路径名仅缺少最后 4 个字符(“Temp\”的“emp\”) - 所有其他字符均有效。

标签: delphi winapi path delphi-2010


【解决方案1】:

国土安全部页面上有关于此 Windows API 函数的说明:

"返回缓冲区 GetLongPathName() 和类似的 函数可能会返回截断的 路径并导致难以发现的错误。”

https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/753-BSI.html

如果您有源代码,您可以检查一下本文描述的问题是否存在于 Delphi 2010 实现中。

【讨论】:

  • 你是对的,我也发现了这一点,我的“讨厌的解决方法”是最初将 Len 设置为 MAX_PATH 并检查 GetLongPathName() 的结果,但我想知道为什么 Embarcadero 使用另一种方法。 ..但感谢您发布此内容,因为它验证了我的方法。
  • 您应该将此报告给 QC。
  • 那么问题出在哪里?问题中的代码正确调用了该函数两次,不是吗?一次找出所需的长度,然后第二次真正填充缓冲区。您引用的代码首先分配缓冲区,以便对该函数的第一次调用可能有效,但如果它失败,它会分配一个新的缓冲区并使用它。这真的是一个重要的区别吗?这篇文章警告不要假设第一次调用在给定 MAX_PATH 大小的缓冲区时总是会成功。该警告如何适用于这种情况?
【解决方案2】:

如果你尝试会发生什么:

var
  longpath : string;

SetLength(longpath,MAX_PATH);
SetLength(longpath, GetLongPathName(PChar(TmpDir),PChar(LongPath),MAX_PATH));

这对我有用,你的版本截断了路径。

【讨论】:

  • 这就是我在“解决方法”中所做的 - 如果问题发生在您的机器上:如果 TPath.GetTempPath() 函数对您有用,会很有趣吗?
  • 此代码可能会给您留下比 Max_Path 更长的字符串,但只分配了 Max_Path 字符。即Length(longpath) > StrLen(PChar(longpath))。您可能还会留下一个带有垃圾的字符串——当缓冲区太小时,文档没有说明函数在缓冲区中存储的内容。安全公告和文档都描述了避免该问题的方法。
  • 好的,这里要提一下,GetLongPathName的返回值很重要,应该检查一下。
  • GetTempPath() 对我来说很好。看起来我将不得不修改我当前的代码以检查正确的长度,然后检查结果是否 >0 以确保。
猜你喜欢
  • 1970-01-01
  • 2016-05-05
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多