Как фрагмент CSS разметки сломал C++ компилятор




Picture 1

В методологии статического анализа применяются разные технологии. Одна из них - препроцессирование файлов непосредственно перед их анализом. Препроцессированные файлы создаёт компилятор, запускаемый в специальном режиме работы. К сожалению, этот режим не очень хорошо тестируется, как показывает наш многолетний опыт разработки статического анализатора кода. В этой заметке приведу пример свеженайденного бага в С++ компиляторе от Microsoft.

Введение

Для демонстрации возможностей статического анализатора PVS-Studio наша команда проверяет исходный код Open Source проектов. Это существенный вклад в качество открытого программного обеспечения, дополнительная реклама и тестирование анализатора. Иногда мы выявляем очень необычные проблемы в компиляторах, с которыми сложно что-то сделать на стороне анализатора. Так, коллега недавно писал статью "Перестал анализироваться файл с директивой 'import' (compiler internal error 'msc1.cpp'). Что делать?", чтобы помочь нашим пользователям в решении "чужой" проблемы.

Причём тут CSS?

Не менее интересный баг был найден мной только что при проверке большого проекта. Компилятор Microsoft для C/C++ версии 19.16.27027.1 (Visual Studio v15.9.9) выдал такую ошибку при анализе нескольких файлов:

fatal error C1021: invalid preprocessor command 'tooltiphint'

Очевидно, это не директива препроцессора, но что же это? Это фрагмент CSS кода:

#tooltiphint {
  position: fixed;
  width: 50em;
  margin-left: -25em;
  left: 50%;
  padding: 10px;
  border: 1px solid #b0b0b0;
  border-radius: 2px;
  box-shadow: 1px 1px 7px black;
  background-color: #c0c0c0;
  z-index: 2;
}

После просмотра фрагмента стало понятно, что компилятор ошибается во время препроцессирования файла, но при этом код компилируется успешно. Фрагмент CSS кода является частью строкового литерала C++ кода. Вот так выглядит пример кода, достаточный для повторения ошибки:

std::string test = R"<<<(
<style type="text/css">
body { color:#000000; background-color:#ffffff }
body { font-family:Helvetica, sans-serif; font-size:10pt }

#tooltiphint {
  position: fixed;
  width: 50em;
  margin-left: -25em;
  left: 50%;
  padding: 10px;
  border: 1px solid #b0b0b0;
  border-radius: 2px;
  box-shadow: 1px 1px 7px black;
  background-color: #c0c0c0;
  z-index: 2;
}
.macro {
  color: darkmagenta;
  background-color:LemonChiffon;
  /* Macros are position: relative to provide base for expansions. */
  position: relative;
}

</style>
</head>
<body>)<<<";

Приведённый фрагмент кода не мешает успешной компиляции, но, в то же время, в режиме препроцессирования (флаг /P) возникнет ошибка.

Вот такая непростая жизнь у разработчиков статических анализаторов :). Вроде виноват не PVS-Studio, но всё равно мы должны заниматься с подобными проблемами. Впрочем, в этом нет чего-то нового. С некоторыми другими подобными случаями можно познакомиться в статье "PVS-Studio и враждебная среда обитания".

Заключение

Эта проблема будет отправлена в официальный баг-трекер, но оперативное решение проблемы вряд ли возможно. Например, проблема с директивой #import, выявленная нами несколько месяцев назад, о которой я писал вначале, будет исправлена только в следующем релизе Visual Studio. Т.к. релиз новой Visual Studio 2019 состоится уже через неделю, скорее всего, этот баг не успеют исправить к этой дате. Пользователям PVS-Studio рекомендуем также воспользоваться макросом PVS_STUDIO.

UPD: A fix for this issue has been released in VS 2019 16.0 Preview 4 and VS 2019 16.0 RC.



Найдите ошибки в своем C, C++, C# и Java коде

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

goto PVS-Studio;


Найденные ошибки

Проверено проектов
344
Собрано ошибок
12 970

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;