Бестиарий программирования
559 subscribers
198 photos
3 videos
3 files
245 links
Наблюдения за жизнью ошибок в коде.
Андрей Карпов.

ГОСТ Р 71207-2024, ГОСТ Р 56939-2024, РБПО, Статический анализ кода
加入频道
РБПО-046. Процесс 8 — Формирование и поддержание в актуальном состоянии правил кодирования (часть 2/4)

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

Они не правы. Я считаю, что даже не очень хороший стандарт лучше, чем его отсутствие. Однако я не говорю, что надо мучиться и преодолевать неудобства. Можно и нужно совершенствовать регламенты. Собственно, это даже отражено в названии рекомендуемого восьмого процесса РБПО — формирование и поддержание в актуальном состоянии правил кодирования.

В любом случае, код должен оформляться единообразно. Иначе неизбежны проблемы при совместной разработке и поддержке проекта. А мы в рамках темы РБПО говорим о проектах, где участвуют много разработчиков, а не об индивидуальном пет-проекте.

Есть ещё одна проблема, которая возникает, если нет единого подхода к написанию и оформлению кода: как вносить правки в код коллег, оформленный в их собственном стиле? Хорошего варианта нет:

1. Написать нужный код в своём стиле. Постепенно получится каша из несвязанных стилей. Это то же самое, когда вообще ни у кого нет никакого стиля написания кода. Код со временем при совместной работе будет становиться всё хуже и непонятнее всем сразу.

2. Постараться подстроиться под код коллег и написать в их стиле. На практике не сработает, так как на самом деле программист не знает, что это за стиль. А если даже ему расскажут, он всё равно забудет или запутается, ведь сложно запомнить все рассказанные ему варианты написания. В общем, и это не рабочий подход.

3. Отрефакторить код коллег под свой стиль. Большая, пустая трата времени и большие diff-ы, в которых будет невозможно понять, где рефакторинг, а где, собственно, нужные изменения.
Надеюсь, что у вас в компании уже давно принят стандарт кодирования. Тогда достаточно это просто переоформить в регламент, а всё, что я здесь пишу, прочитать по диагонали. Однако если стандарта кодирования нет, внедрение РБПО — хороший момент наконец создать эту полезную вещь! Впрочем, стандарт кодирования однозначно принесёт пользу даже вне контекста РБПО. Так что если у вас его нет, прямо сейчас откройте задачу на его создание :)

Если я всё ещё не убедил, расскажу последнюю историю. Общаясь с одним человеком, который проработал в коммерческой компании почти с момента её основания до становления успешным большим бизнесом, я спросил, что бы он устроил по-другому в работе, если бы вернулся лет на 15 назад? Ответ, в том числе, содержал следующий момент:
Я бы настоял принять единый стандарт кодирования на всю компанию. Мы упустили этот момент, и сейчас мы по факту имеем свои собственный стандарты кодирования для С++ и Java в разных командах, работающих над своими проектами. Это очень неудобно, но сейчас внедрять единый стиль и переформатировать код всех этих проектов нереально.

В общем, чем раньше вы позаботитесь о единообразии, тем лучше!
1🔥1
РБПО-047. Процесс 8 — Формирование и поддержание в актуальном состоянии правил кодирования (часть 3/4)

Артефакты реализации требований (что, собственно, представляет собой регламент):
5.8.3.1 Регламент оформления исходного кода и безопасного кодирования должен содержать:
- информацию о способах оформления исходного кода (например, способы выбора наименований переменных, функций, классов и т. п.; стиль отступов при оформлении логических блоков; способы ограничения логических блоков; правила использования пробелов при оформлении логических и арифметических выражений; стиль комментариев и правила документирования кода; ограничения [например, размер строк кода по горизонтали, строк в модуле и т. п.)];
- перечень запрещенных способов кодирования, конструкций и т. п. (например, указание паролей в исходном коде ПО в явном виде, использование «магических чисел» и т. п.);
- примеры опасных и безопасных конструкций для используемых языков программирования;
- область применения правил кодирования;
- порядок проверки выполнения правил кодирования для вносимых изменений в исходный код ПО;
- рекомендации разработчиков языков программирования по использованию стандартов кодирования (языков программирования, в том числе собственной разработки), принятые разработчиком ПО.

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

Думаю, лучше всего начать с такой замечательной книги, как "Совершенный код" Стива Макконнелла ("Code Complete", Steve McConnell).

Из неё можно почерпнуть очень много, например, про табличное форматирование кода. Оно помогает делать код визуально более красивым и лёгким для восприятия. А ещё это один из способ бороться с "кодом-колбасой". Так я называю длинные строчки кода. Про них я поговорю в следующем посте.

C++ программисты могут почерпнуть идеи из вот этого документа с хорошими мыслями и отсылками к другим стандартам: Coding Standards.

Если говорить про "перечень запрещённых способов кодирования, конструкций и т. п." и "примеры опасных и безопасных конструкций для используемых языков программирования", то можно взять некоторые идеи из таких стандартов, как MISRA C и MISRA C++. Однако надо понимать, что это специализированные стандарты из мира встраиваемых систем, и заимствовать что-то оттуда для других сфер программирования может быть бестолковой идеей.

Вообще, стоит проговорить, что существует множество разных стандартов кодирования, таких как MISRA C/C++, CWE (Common Weakness Enumeration), OWASP Application Security Verification Standard (ASVS), SEI CERT Coding Standard и так далее. Но с точки зрения рационального использования времени бессмысленно их читать для составления правил кодирования, а затем вручную контролировать их выполнение. Для этого есть статические анализаторы кода. Собственно, в 8 главе стандарта есть даже их упоминание:
Примечание — Допускается реализовывать проверку правил кодирования средствами компиляции или статического анализа.

Но статический анализ — это отдельный процесс (5.10). Восьмая же глава всё-таки про регламент написания кода, его оформление и выравнивание, правила именования переменных, функций и так далее.

Дополнительные ссылки:

1. Лекция 8. Стандарт кодирования PVS-Studio и приёмы при разработке эффективных С++ диагностик. Видео 2019 года, поэтому кое-что у нас уже поменялось. Сейчас я бы рассказал немного по-другому и привёл бы иные примеры. Тем более учитывая, что за это время мы переписали ядро C++ анализатора. Но в целом ok, полезное. Предлагаю к просмотру.

2. Wikipedia. Стандарт оформления кода. См. отсылки на стандарты.
Появился проект ГОСТа на SCA:
Защита информации. Разработка безопасного программного обеспечения.
Композиционный анализ программного обеспечения. Общие требования.
🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
Торжественный запуск PVS-Studio на испытаниях статических анализаторов кода под эгидой ФСТЭК
🔥163
РБПО-048. Процесс 8 — Формирование и поддержание в актуальном состоянии правил кодирования (часть 4/4)

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

Пример рефакторинга длинной строки можно посмотреть в статье "Учимся рефакторить код на примере багов в TDengine, часть 1: про колбасу". Первая картинка как раз из этой заметки взята.

Ограничение на длину строк — это один из примеров, что можно включить в стандарт кодирования.
Заметить опечатку мешают не только длинные строки, но и неаккуратно отформатированные. На второй картинке пример функции из проекта Apache Flink.

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

Ошибка найдена с помощью статического анализатора кода PVS-Studio: V6001 There are identical sub-expressions 'processedData' to the left and to the right of the '==' operator. CheckpointStatistics.java(229)

Вот она:
processedData == processedData

Переменная сравнивается сама с собой. Хотя ошибка найдена, лучше заниматься не её поиском, а профилактикой. Если оформить код более красиво (таблицей), как показано на третьей картинке, ошибка более заметна.
Конечно, это не гарантирует, что ошибка не будет пропущена. Речь о том, чтобы снизить вероятность её допустить и просмотреть на обзорах кода.

Чтобы расставлять меньше пробелов и реже переформатировать код, лучше ещё доработать стиль оформления: см. рисунок 4.

Объяснение, чем такой вариант лучше, выходит за рамки поста. Предлагаю вашему вниманию эту заметку "Форматирование кода таблицей", где это момент объясняется на примерах.

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

Внедрение стандарта кодирования повысит общий уровень вашей разработки, что положительно повлияет на безопасность разрабатываемых приложений. Так что меры, перечисляемые в ГОСТ Р 56939-2024, имеют ценность в практической плоскости.

Дополнительно можно настроить и использовать инструменты автоматизированного форматирования кода, такие как:
ClangFormat;
Uncrustify.
🔥4
Forwarded from PVS-Studio
Цикл "Вокруг РБПО за 25 вебинаров: ГОСТ Р 56939-2024"!

Друзья, напоминаем, что совместно с Учебным Центром "МАСКОМ" мы организовываем цикл вебинаров, посвященных разбору 25 процессов РБПО.

Сегодня в 16:00 состоится шестой вебинар ⚡️

Приглашенный эксперт: Хмелëв Игорь Геннадьевич, заместитель директора специальных разработок НПО Эшелон

Тема: "Разработка, уточнение и анализ архитектуры программного обеспечения"

Регистрация на этот и последующие вебинары доступна по ссылке🔗

Присоединяйтесь к путешествию вокруг РБПО вместе с нами!

#вебинар
3
Сейчас начинается OWASP AI Agentic Top 10 Project Kick-off - Global Call https://www.youtube.com/watch?v=mMLG6YNm6A8
Будет представлена альфа версия будущего Top 10 для агентов от OWASP
3
Запись шестой встречи «Вокруг РБПО за 25 вебинаров». Разработка, уточнение и анализ архитектуры программного обеспечения.

Приглашённым экспертом стал Игорь Хмелёв, заместитель директора специальных разработок НПО «Эшелон».

P.S.
В ходе вебинара звучал вопрос о сертификации используемых инструментальных средств (статически анализаторы, динамические т.д.). В связи с этим стоит вспомнить про недавнее методическое указание № 2025-07-011.
Тип недостатка: Необоснованный выбор инструментов, в том числе инструментов статического анализа исходного кода, для выстраивания и выполнения процессов РБПО.

И вот текстовая расшифровка фрагмента ответа представителя ФСТЭК, который упоминается в рекомендации.
👍6
Экскурс в неопределенное поведение C++

В прошлом году я помог Дмитрию Свиридкину подготовить и опубликовать цикл из 12 статей «Путеводитель C++ программиста по неопределённому поведению». Теперь этот расширенный, доработанный и обобщенный материал доступен в виде печатной книги:

Экскурс в неопределенное поведение C++ / Д. О. Свиридкин, А. Н. Карпов, – СПб.: БХВ-Петербург, 2025. – 384 с. – (Профессиональное программирование)

ISBN 978-5-9775-2073-7
Книга представляет собой обширный справочник типичных, а также очень редко встречающихся ошибок, характерных для программ на C++, Rust и других языках для низкоуровневого и системного программирования, в частности на ассемблере. Все рассмотренные проблемы так или иначе связаны с неопределенным, неуточненным и определяемым реализацией поведением языковых конструкций. Наибольшее внимание уделено неопределенному поведению, возможным признакам его присутствия в программах и методам поиска, диагностики и устранения такого поведения.

Книгу можно найти в offline и online магазинах.
👍114
РБПО-049. Процесс 9 — Экспертиза исходного кода (часть 1/3)

Цели девятого процесса по ГОСТ Р 56939-2024:
Обеспечение соответствия исходного кода ПО предъявляемым к нему требованиям.

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

Первый вид работ — экспертиза кода, создаваемого в компании штатными разработчиками. Другими словами, это классические обзоры кода (code review), только более упорядоченные, чем обычно это бывает при разработке ПО. Именно к этому относятся артефакты из п 5.9.3., такие как "описание основных проверок (например сценариев, шаблонов, чек-листов) и т.д. К этой теме я вернусь в следующей части.

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

Второй вид работ — экспертиза стороннего кода, который команда включает в проект. Понятно, что нереально проводить полноценный обзор кода подключаемых библиотек. Здесь скорее идёт речь о таких вещах, как определение для заимствованного кода поверхности атаки (см. процесс 7) с помощью инструментов и привлечения экспертов.

В случае, если стоит выбор среди несколько схожих по функциональности библиотек (компонентов), то экспертиза кода экспертом и с помощью статического анализа поможет выбрать наиболее качественную, а значит более безопасную реализацию. См. также статью "Почему важно проводить статический анализ открытых библиотек, которые вы добавляете в свой проект".

Третий вид работ — дополнительный ручной анализ собственного кода, для которого отсутствует инструменты статического анализа. Т.е. если у вас есть немного кода на языке, для которого нет анализатора, то вы должны вручную проверить всё то, что проверял бы анализатор. В принципе, этот тот же обор кода, но чек-лист в этом случае может содержать больше пунктов. Например, если в других частях проекта анализаторы кода следят за правилами именования переменных, то на обзоре кода вы должны следить за этим сами. Если непокрытого анализатором кода много, то у вас проблема, с которой предстоит что-то сделать.

Что делать, если подключается сторонняя библиотека на языке, для которого у вас нет анализатора? Смотрите, с точки зрения РБПО, если вы включили в проект сторонний код, то теперь это ваш код, за который вы ответственны. Следовательно, вы должны выбрать дополнительный инструмент статического анализа и включить его в свои процессы разработки.

Что делать, если библиотека обязательно нужна большая (ручной обзор невозможен) и при этом она на языке, для которого статического анализатора не существует в природе? Вот тут даже не знаю, что ответить. Понятно, что есть проблема, но как её решить затрудняюсь подсказать. Возможно, надо подумать в сторону каких-то компенсационных мер... Хз. Может, кто-то в комментариях подскажет, что следует делать в таком случае.
👍1
РБПО-050. Процесс 9 — Экспертиза исходного кода (часть 2/3)

Продолжим читать девятый раздел ГОСТ Р 56939-2024. Требования к реализации:
5.9.2.1 Разработать регламент проведения экспертизы исходного кода ПО.

На языке программистов: разработать порядок и чек-листы проведения обзоров кода (code review). Скорее всего, практика обзоров кода так или иначе уже существует в вашей компании, а с внедрением РБПО просто пришло время её формализовать, сделать более чёткой/строгой и обязательной.
5.9.2.2 Проводить экспертизу определенных областей кода ПО (в первую очередь для модулей (компонентов) ПО, составляющих поверхность атаки) в соответствии с регламентом проведения экспертизы исходного кода ПО.

Очевидный, но от этого не менее важный пункт, что надо процесс не только разработать, но и внедрить его регулярное выполнение. Надеюсь, с этим сложностей быть не должно, поскольку code review — одна из старейших базовых практик написания качественного кода.
Неформальные процедуры обзоров передавались от человека человеку в общей культуре программирования задолго до того, как информация об этом стала появляться в печатных материалах. Необходимость обзоров была настолько очевидна лучшим программистам, что они редко упоминали об этом в статьях и книгах, тогда как худшие программисты считали, что они настолько хороши, что их работа не нуждается в обзорах.

Дениел Фридмен и Джеральд Вайнеберг (Daniel Freedman and Gerald Weinberg)
5.9.2.3 Проводить экспертизу кода рекомендуется с использованием программных средств, автоматизирующих проведение экспертизы и интегрированных с системой контроля версий разрабатываемого ПО.

Речь про системы автоматизирования обзоров кода (здесь не путать со статическим анализом), в том числе позволяющие делать это удалённо.

Примером такой системы является RBCommons. Мы пробовали её в далёком 2016 году, но она не прижилась. Сейчас единого подхода нет, действуем из соображений удобства. Кто-то собирается просто в офисе возле компьютера. Кто-то созванивается в Zoom с демонстрацией экрана. Кто-то в GitHub смотрит PR коллег. В общем, мы ценим процесс обзор кода, но пока не чувствуем потребности в жёсткой автоматизации. Возможно, коллектив ещё небольшой, квалифицированный, и у нас просто нет проблемы, что кто-то игнорирует процессы обзора кода.
РБПО-051. Процесс 9 — Экспертиза исходного кода (часть 3/3)

Теперь перейдём к артефактам реализации требований девятого процесса ГОСТ Р 56939-2024:
5.9.3.1 Регламент проведения экспертизы исходного кода ПО должен содержать следующие сведения:
- обязанности сотрудников и их роли при проведении экспертизы исходного кода ПО;
- базовые требования к экспертизе (количество участников; области кода, подлежащего экспертизе; используемые инструменты и т. д.);
- описание основных проверок (например, сценариев, шаблонов, чек-листов) проведения экспертизы исходного кода ПО.

Думаю, суть описана достаточно и понятно. Конкретика уже зависит от ваших нужд, предпочтений, возможностей, типа проекта и т.д. Если хочется от чего-то оттолкнуться, то уже в который раз рекомендую книгу Стива Макконнелла "Совершенный код" ("Code Complete", Steve McConnell). В ней очень много и хорошо написано про обзоры кода.

Проводя обзор кода, важно не забывать про такие высокоуровневые задачи, как:

• обучение членов команды, передача опыта и знаний о проекте новым сотрудникам;
• поиск высокоуровневых ошибок, недостатков выбранных архитектурных решений, неэффективных/опасных подходов в реализации.

Это я вот к чему. Есть риск увлечься на обзорах вопросами оформления кода и поиском опечаток. Это, конечно, тоже полезно и является частью процесса обзоров. Однако часть опечаток помогут найти статические анализаторы кода. Тем более что некоторые опечатки человеку сложно заметить. Вопросы оформления помогают решить правила кодирования (см. предыдущий восьмой процесс) и утилиты автоформатирования. А вот обучение, передача опыта, обсуждение алгоритмов и выявление высокоуровневых недостатков в безопасности и в целом — это всё остаётся только на людях. Полезно не забывать про всё это во время обзора кода.
5.9.3.2 Результаты экспертизы кода должны содержать следующие сведения:
- информацию о проанализированных модулях (компонентах) ПО;
- перечень необходимых изменений;
- вопросы к частям кода, экспертиза которых затруднена и требует дополнительных разъяснений;
- предложения по улучшению.

Здесь, думаю, программистам всё тоже понятно. Остановлюсь только на пункте "вопросы к частям кода, экспертиза которых затруднена и требует дополнительных разъяснений".

Считается, что на обзорах кода тот, кто написал код, не может давать разъяснения, как он работает. Если код непонятен коллегам, значит его надо переписать или снабдить комментариями. Код должен стать самодостаточным для понимания.

Полностью поддерживаю эту идею. На практике, конечно, это тяжело воплотить. Слишком жёсткий подход будет затягивать цикл обзоров фрагмента кода и делать этот процесс в целом очень медленным и трудозатратным. А иногда надо просто что-то быстро сделать, а не заниматься созданием некого идеального кода :) Так что везде нужен баланс. Однако идея хорошая, и по возможности стоит приближаться к её воплощению в реальности :)

P.S. Про написание комментариев. Комментарии должны отвечать не на вопрос "что делаем?", а на вопрос "зачем/почему делаем?". Подробнее — в главе N53 "60 антипаттернов для С++ программиста".