понедельник, 29 ноября 2010 г.

Путаница в параметрах

Это перевод Parameter confusion. Автор: Майкл Каплан.

Функция LCMapString выглядит так, будто бы она имеет ясный и однозначный смысл своих параметров. Посмотрите на заголовок:
function LCMapString(
  Locale: LCID;       // ИД локали
  dwMapFlags: DWORD;  // тип преобразования
  lpSrcStr: LPCTSTR;  // исходная строка
  cchSrc: Integer;    // число символов в исходной строке
  lpDestStr: LPTSTR;  // целевой буфер
  cchDest: Integer;   // размер целевого буфера
): Integer;
И для большинства типов использования LCMapString это справедливо.

Ну, кроме случая с ключами сортировки.

Когда вы работаете с ключами сортировки, то изменяются две вещи:
  1. Значение cchDest теперь не число символов, а размер в байтах.
  2. Возвращаемое значение больше не число символов, записанных в lpDestStr, а размер в байтах.
Очевидно, такое поведение имеет проблемы с точки зрения безопасности кода (см. примеры в теме "Security Considerations: International Features" Platform SDK).

Я думаю, что если бы мы проектировали эту функцию сегодня, то одного этого было бы достаточно, чтобы разбить функцию на две.

Но на практике путаница здесь такова, что при ошибке вы получите в два раза больший буфер, чем необходимо - скорее, это проблема чрезмерного потребления ресурсов, чем безопасности.

Я думаю, что ключевой момент здесь - внимательное чтение документации :-)

Это поведение также может вызывать (и иногда вызывает!) путаницу и внутри Microsoft, поскольку внутренние подпрограммы, которые обрабатывают ключи сортировки, будут, конечно же, именовать этот параметр как cbDest, а не cchDest. Поэтому, если вы просто посмотрите на такой код и увидите, как кто-то берёт cchDest и передаёт другой функции как cbDest - вы справедливо задумаетесь, нет ли здесь бага. Впрочем, это наши проблемы...

This post brought to you by "ޛ" (U+079b, a.k.a. THAANA LETTER THAALU)

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.