Почему _splitpath_s () принимает строковый буфер нестандартного размера для возврата буквы диска?

Маленькая деталь попалась на глаза при чтении документации _splitpath_s(). Он принимает путь к элементу диска (например, C: \ Temp \ MyFile.exe) в его 1улица параметр, а затем разбивает его на привод, каталог, папка а также расширение имена. Тем не менее, странно то, что он запрашивает длину строкового буфера, который будет содержать имя диска в ответ на его 3й параметр.

Насколько я знаю, буква диска может быть только двухбуквенной строкой; буква, за которой следует точка с запятой, например 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
);

1

Решение

Суть _s функции должны быть параноиком по поводу переполнения буфера. Поэтому все буферы должны быть связаны с размером.

Ваше предложение использовать двухсимвольную строку будет означать, что либо двоеточие будет опущено (что с точки зрения использования будет раздражающим), либо это будет означать, что строка не заканчивается NUL, что, вероятно, является неожиданным (особенно если это будет несовместим со всеми другими выходными параметрами, которые являются NUL-прекращено), что может привести к другим уязвимостям безопасности.

Даже если вы изменили свое предложение об использовании буфера фиксированного размера из трех символов вместо двух, в C объявление параметров массива для функций на самом деле ничего не дает; компилятор не будет принудительно устанавливать, что аргумент является массивом правильного размера. То есть такая функция:

 void foo(int array[3]);

на самом деле не отличается от:

 void foo(int* array);

Если _splitpath_s не взял driveNumberOfElements параметр, для вызывающих абонентов было бы легче случайно передать слишком малые буферы. Хотя это правда, что вызывающие абоненты все еще могут делать это в своей текущей форме, наличие явного driveNumberOfElements параметр должен заставить звонящих платить немного внимание к этому.

Наконец, теоретически, когда-нибудь диски могут не ограничиваться отдельными символами, поэтому версия _splitpath_s это занимает driveNumberOfElements Параметр немного более ориентирован на будущее. (Однако на практике такое изменение может привести к поломке большого количества существующего кода.)

2

Другие решения

Других решений пока нет …