Анализатор PVS-Studio регулярно пополняется новыми правилами диагностики. Как ни странно, диагностика часто выявляет подозрительные фрагменты кода еще до окончания работы. Например, такая ситуация может случиться при тестировании на проектах с открытым исходным кодом. Итак, давайте взглянем на одну из этих интересных находок.

Как упоминалось ранее, одним из этапов тестирования диагностического правила является проверка его работы на реальной кодовой базе. Для этого у нас есть набор избранных проектов с открытым исходным кодом, которые мы используем для анализа. Очевидным преимуществом такого подхода является возможность увидеть поведение диагностического правила в реальных условиях. Есть и менее очевидное преимущество. Иногда можно встретить такой интересный случай, что грех не написать о нем статью. :)

Теперь давайте посмотрим на код из проекта Bouncy Castle C# и найдем в нем ошибку:

public static string ToString(object[] a)
{
  StringBuilder sb = new StringBuilder('[');
  if (a.Length > 0)
  {
    sb.Append(a[0]);
    for (int index = 1; index < a.Length; ++index)
    {
      sb.Append(", ").Append(a[index]);
    }
  }
  sb.Append(']');
  return sb.ToString();
}

Для тех, кто любит обманывать и подглядывать, я добавил картинку, чтобы вы не догадались.

Я уверен, что некоторые из вас не смогли бы увидеть ошибку без использования IDE или документации по классу StringBuilder. Произошла ошибка при вызове конструктора:

StringBuilder sb = new StringBuilder('[');

Собственно, именно об этом нас и предупреждает статический анализатор PVS-Studio: V3165 Символьный литерал ‘[‘ передается в качестве аргумента типа ‘Int32’, тогда как аналогичная перегрузка со строковым параметром существует. Возможно, вместо этого следует использовать строковый литерал. Массивы.cs 193.

Программист хотел создать экземпляр типа StringBuilder, где строка начинается с символа ‘[‘. Однако из-за опечатки у нас будет объект без символов с емкостью 91 элемент.

Это произошло потому, что программист использовал одинарные кавычки вместо двойных. Вот почему была вызвана неправильная перегрузка конструктора:

....
public StringBuilder(int capacity);
public StringBuilder(string? value);
....

При вызове конструктора символьный литерал ‘[‘ будет неявно приведен к соответствующему значению типа int (91 в Unicode). Из-за этого будет вызван конструктор с параметром типа int, задающим начальную емкость. Хотя программист хотел вызвать конструктор, который устанавливает начало строки.

Чтобы исправить ошибку, разработчик должен заменить символьный литерал строковым литералом (т.е. использовать «[» вместо «[‘). Это вызовет правильную перегрузку конструктора.

Мы решили сделать все возможное и расширили список случаев, рассмотренных диагностикой. В результате, помимо символьных литералов, теперь рассматриваются некоторые другие выражения типа char. Таким же образом проверяем и методы.

Описанная выше диагностика была добавлена ​​в релизе PVS-Studio 7.11. Вы можете самостоятельно скачать последнюю версию анализатора. Вы увидите, что может сделать диагностика V3165, а также другие диагностики для C, C++, C# и Java.

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

P.S. Эта ошибка уже исправлена ​​в кодовой базе текущего проекта. Впрочем, это не меняет того факта, что он существует в коде уже некоторое время, а статический анализ позволяет выявлять такие проблемы и устранять их на самых ранних стадиях.