Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
История о том, как PVS-Studio нашёл оши…

История о том, как PVS-Studio нашёл ошибку в библиотеке, используемой в... PVS-Studio

08 Авг 2019

Это небольшая история о том, как с помощью PVS-Studio удалось найти ошибку в исходном коде библиотеки, используемой в PVS-Studio. Причём не теоретическую, а фактическую - ошибка проявлялась на практике при использовании библиотеки в анализаторе.

0654_CMDParserBug_ru/image1.png

В PVS-Studio_Cmd (а также некоторых других утилитах) мы используем специальную библиотеку для разбора аргументов командной строки - CommandLine.

Сегодня я занимался поддержкой нового режима в PVS-Studio_Cmd, и как раз так получилось, что пришлось использовать эту библиотеку разбора аргументов. В процессе написания кода также отлаживаю его, так как приходится работать с незнакомыми API.

Итак, код написан, компилируется, запускаю на исполнение, иии...

0654_CMDParserBug_ru/image2.png

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

На всякий случай смотрю комментарии к вызываемому методу. Очень маловероятно, что в них описаны условия возникновения исключения типа NullReferenceException (так как обычно, как мне кажется, исключения этого типа - непредусмотренные).

0654_CMDParserBug_ru/image3.png

В комментариях к методу информации ни о каком NullReferenceException нет (что, впрочем, ожидаемо).

Чтобы посмотреть, из-за чего конкретно возникает исключение (и где), решил загрузить исходный код проекта, собрать и подключить к анализатору отладочную версию библиотеки. Исходный код проекта доступен на GitHub. Необходима версия 1.9.71, так как именно такая сейчас используется в анализаторе.

Загружаю соответствующую версию исходного кода, собираю, подключаю отладочную библиотеку к анализатору, запускаю код на исполнение и вижу:

0654_CMDParserBug_ru/image4.png

Итак, место возникновения исключения понятно - helpInfo имеет значение null, из-за чего возникает исключение типа NullReferenceException при обращении к экземплярному свойству Left.

И тут я призадумался. В последнее время PVS-Studio для C# был неплохо улучшен в различных областях, в том числе - в области поиска разыменования потенциально нулевых ссылок. В частности - был порядком улучшен межпроцедурный анализ. Поэтому мне сразу же стало интересно проверить исходный код, чтобы понять, сможет ли PVS-Studio найти обсуждаемую ошибку.

Я проверил исходный код, и среди прочих предупреждений увидел именно то, на которое надеялся.

Предупреждение PVS-Studio: V3080 Possible null dereference inside method at 'helpInfo.Left'. Consider inspecting the 2nd argument: helpInfo. Parser.cs 405

Да, вот оно! Именно то, что нужно. Посмотрим на исходный код чуть детальнее.

private bool DoParseArgumentsVerbs(
  string[] args, object options, ref object verbInstance)
{
  var verbs 
    = ReflectionHelper.RetrievePropertyList<VerbOptionAttribute>(options);
  var helpInfo 
    = ReflectionHelper.RetrieveMethod<HelpVerbOptionAttribute>(options);
  if (args.Length == 0)
  {
    if (helpInfo != null || _settings.HelpWriter != null)
    {
      DisplayHelpVerbText(options, helpInfo, null); // <=
    }

    return false;
  }
  ....
}

Анализатор выдаёт предупреждение на вызов метода DisplayHelpVerbText и предупреждает о втором аргументе - helpInfo. Обратите внимание, что этот метод находится в then-ветви оператора if. Условное выражение составлено таким образом, что then-ветвь может быть исполнена при следующих значениях переменных:

  • helpInfo == null;
  • _settings.HelpWriter != null;

Посмотрим тело метода DisplayHelpVerbText:

private void DisplayHelpVerbText(
  object options, Pair<MethodInfo, 
  HelpVerbOptionAttribute> helpInfo, string verb)
{
  string helpText;
  if (verb == null)
  {
    HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, null, out helpText);
  }
  else
  {
    HelpVerbOptionAttribute.InvokeMethod(options, helpInfo, verb, out helpText);
  }

  if (_settings.HelpWriter != null)
  {
    _settings.HelpWriter.Write(helpText);
  }
}

Так как verb == null (см. вызов метода) нас интересует then-ветвь оператора if. Хотя с else ветвью ситуация будет аналогична, рассматривать будем then-ветвь, так как в нашем частном случае именно через неё шло исполнение. Помним, что helpInfo может иметь значение null.

Теперь посмотрим на тело метода HelpVerbOptionAttribute.InvokeMethod. Собственно, его вы уже видели на скриншоте выше:

internal static void InvokeMethod(
    object target,
    Pair<MethodInfo, HelpVerbOptionAttribute> helpInfo,
    string verb,
    out string text)
{
  text = null;
  var method = helpInfo.Left;
  if (!CheckMethodSignature(method))
  {
    throw new MemberAccessException(
      SR.MemberAccessException_BadSignatureForHelpVerbOptionAttribute
        .FormatInvariant(method.Name));
  }

  text = (string)method.Invoke(target, new object[] { verb });
}

helpInfo.Left вызывается безусловно, при том, что helpInfo может иметь значение null. Об этом предупреждал анализатор, это и произошло.

Заключение

Забавно получилось, что с помощью PVS-Studio удалось найти ошибку в коде библиотеки, которая используется в PVS-Studio. Я думаю, это своего рода продолжение ответа на вопрос "Находит ли PVS-Studio ошибки в коде PVS-Studio?". :) Может находить ошибки не только в коде PVS-Studio, но и в коде используемых библиотек.

Напоследок предложу скачать анализатор и попробовать проверить свой проект - вдруг и там удастся найти что-нибудь интересное?

Популярные статьи по теме
PVS-Studio ROI

Дата: 30 Янв 2019

Автор: Андрей Карпов

Время от времени нам задают вопрос, какую пользу в денежном эквиваленте получит компания от использования анализатора PVS-Studio. Мы решили оформить ответ в виде статьи и привести таблицы, которые по…
Эффект последней строки

Дата: 31 Май 2014

Автор: Андрей Карпов

Я изучил множество ошибок, возникающих в результате копирования кода. И утверждаю, что чаще всего ошибки допускают в последнем фрагменте однотипного кода. Ранее я не встречал в книгах описания этого …
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

Автор: Андрей Карпов

Вы угадали, ответ - "42". Здесь приводится 42 рекомендации по программированию, которые помогут избежать множества ошибок, сэкономить время и нервы. Автором рекомендаций выступает Андрей Карпов - тех…
Бесплатный PVS-Studio для тех, кто развивает открытые проекты

Дата: 22 Дек 2018

Автор: Андрей Карпов

В канун празднования нового 2019 года команда PVS-Studio решила сделать приятный подарок всем контрибьюторам open-source проектов, хостящихся на GitHub, GitLab или Bitbucket. Им предоставляется возмо…
Статический анализ как часть процесса разработки Unreal Engine

Дата: 27 Июн 2017

Автор: Андрей Карпов

Проект Unreal Engine развивается - добавляется новый код и изменятся уже написанный. Неизбежное следствие развития проекта - появление в коде новых ошибок, которые желательно выявлять как можно раньш…
Любите статический анализ кода!

Дата: 16 Окт 2017

Автор: Андрей Карпов

Я в шоке от возможностей статического анализа кода, хотя сам участвую в разработке инструмента PVS-Studio. На днях я был искренне удивлён тому, что анализатор оказался умнее и внимательнее меня.
Как и почему статические анализаторы борются с ложными срабатываниями

Дата: 20 Мар 2017

Автор: Андрей Карпов

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

Автор: Андрей Карпов

После большой статьи про проверку операционной системы Tizen мне было задано много вопросов о проценте ложных срабатываний и о плотности ошибок (сколько ошибок PVS-Studio выявляет на 1000 строк кода)…
Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей

Дата: 21 Ноя 2018

Автор: Андрей Карпов

Краткое описание технологий, используемых в инструменте PVS-Studio, которые позволяют эффективно обнаруживать большое количество паттернов ошибок и потенциальных уязвимостей. Статья описывает реализа…
Зло живёт в функциях сравнения

Дата: 19 Май 2017

Автор: Андрей Карпов

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

Комментарии (0)

Следующие комментарии

На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять