1

在阅读_splitpath_s(). 它在其第一个参数中获取磁盘项目的路径(例如 C:\Temp\MyFile.exe),然后将其拆分为驱动器目录文件夹扩展名。然而,奇怪的是,它会在其第三个参数中询问将保存驱动器名称的字符串缓冲区的长度。

据我所知,驱动器号只能是两个字母的字符串。一个字母后跟一个分号,如A:, B:, C:, 等。因此,在所有情况下,它必须始终是两个字符的字符串。但如果是这样,为什么要_splitpath_s()询问驱动器号的长度?在任何情况下哪个驱动器号可以采用不同的格式?如果它不询问它的长度并假设它是 2,那么最坏的情况会发生什么问题?

errno_t _splitpath_s(
   const char * path,
   char * drive,
   size_t driveNumberOfElements,
   char * dir,
   size_t dirNumberOfElements,
   char * fname,
   size_t nameNumberOfElements,
   char * ext, 
   size_t extNumberOfElements
);
4

1 回答 1

2

函数的重点_s是对缓冲区溢出保持偏执。因此,所有缓冲区都应与大小相关联。

您建议使用两个字符的字符串意味着要么省略冒号(从使用角度来看这很烦人),要么意味着该字符串不是以 NUL 结尾的,这可能是出乎意料的(尤其是因为它会是与所有其他NUL 结尾的输出参数不一致),然后可能导致其他安全漏洞。

即使您修改了建议以使用三个字符而不是两个字符的固定大小缓冲区,在 C 中,将数组参数声明给函数实际上并没有任何作用;编译器不会强制参数是正确大小的数组。也就是说,像这样的函数:

 void foo(int array[3]);

实际上与以下没有任何不同:

 void foo(int* array);

如果_splitpath_s不带driveNumberOfElements参数,调用者会更容易意外传递太小的缓冲区。虽然调用者仍然可以以当前形式执行此操作,但显式driveNumberOfElements参数的存在应该让调用者对此有所注意。

最后,理论上,驱动器有一天可能不会仅限于单个字符,因此_splitpath_s采用driveNumberOfElements参数的版本更具前瞻性。(然而,在实践中,这样的改变会破坏很多现有的代码。)

于 2013-08-05T21:19:04.730 回答