Как стать автором
Обновить

Комментарии 50

НЛО прилетело и опубликовало эту надпись здесь
Вот, кстати, замечательное предложение, поддерживаю!
Очень подозрительная статья. Признайтесь, кто вам за неё заплатил?!
Есть инсайт, что эту статью (причем скорее не напрямую, а косвенно) оплатили
вот эти хитрые ребята
компания PVS-Studio

Не развеяли ("раз оправдываются — значит, есть что скрывать") :-)
И не думаю, что те, кто вас в чём-то обвиняет — тролли. Скорей просто не осознают масштабов человеческого эгоцентризма: они сосредоточены на своих (или нравящихся им) проектах, вы — на своём анализаторе (поэтому лично я не верю в вашу предвзятость: вам должно быть не до того… некогда гнобить чужие проекты, надо совершенствовать свой и хвастаться им), и вам с ними трудно друг друга понять.

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

Безо всякого стеба — неплохое решение!
На самом деле, цель не достигнута. Вскользь, да, доводы есть, но на них не сделан акцент, вместо этого приводятся убеждения вида «мамой клянусь».
А стоило бы сделать упор вот на что:
— Поскольку код проектов открыт, а триальная версия анализатора доступна, то любой скептик может провести собственный аудит кода, что не требует от аудитора выдающихся способностей или уймы времени.
— Даже если анализатор нашел множество ошибок (а чем больше проект, тем их должно быть больше), это еще не значит, что код плохой. Предупреждение может быть или ложным срабатыванием (коих ожидается гораздо больше, чем настоящих ошибок), или быть несущественным (ошибочный код или не выполняется почти никогда, или нивелируется поведением корректного кода). И наоборот, просто плохой стиль кода может быть абсолютно корректным с точки зрения как статического анализатора, так и самого рантайма (скажем, обфускация кода не меняет количество предупреждений).
— Не только физически невозможно, но и неинтересно проверять всех конкурентов проверенной программы, а уж тем более проводить сравнение по выявленным огрехам. А тем более каждый аудит оформлять в виде пухлой статьи.
— Проекты с закрытым кодом не могут быть проверены либо из-за недоступности исходников, либо из-за отсутствия права публиковать фрагменты кода. Поэтому статьи только об оперсорс проектах.
— Вор громче всех кричит о том, что у него что-то украли: голословные утверждения непроверяемы в силу человеческого фактора. Если уж абсолютно случайная последовательность нулей и единиц может выдать достаточно длинную очередь только нулей или единиц, это ли основание обвинять случайность в предвзятости? Точно так же предвзято относится обвиняющий в предвзятости, при этом ему совершенно необязательно быть троллем.
— Наконец, статьи тоже пишутся людьми. Есть неинтересные проекты, есть неудачно подобранные для статьи предупреждения, да и все что угодно может показаться негативом. Впрочем, все это проверяемо, и каждый может прогнать повторно Студию по коду — возможно, у него статья получится интереснее.
Отличный комментарий. Спасибо.
Поскольку код проектов открыт, а триальная версия анализатора доступна, то любой скептик может провести собственный аудит кода, что не требует от аудитора выдающихся способностей или уймы времени
Разработчики проекта оказались вменяемыми и расторопными, пофиксив критичные баги. Ворох комментов «Вывсёврёти, проверял буквально через два месяца — такого количества багов нет»
Думаю посетители хабра слышали про различные VCS.
Вы, действительно, предвзяты в статьях. Вот пример:
Если проект качественный, то мы пишем, что не смогли найти ошибок
Здесь содержится логическая ошибка. Вы предвзято связываете качество проекта с возможностью нахождения ошибок вашим инструментом, но это не так. Невозможность найти ошибки статическим анализатором слишком мало говорит о качестве и наоборот, что, естественно, не отменяет пользы от использования анализатора.

Какое качество вы имеете в виду?
Думаю речь шла именно о качестве с точки зрения статического анализатора. Это следует из контекста статьи и вообще всего направления деятельности автора и его компании.

Думаю, хоть здесь и нет прямой зависимости, но доля правды есть, и вот почему:
1. статическими анализаторами как раз и пользуются для нахождения ошибок, опечаток и пр., имея целью повышения качества кода (иначе зачем таковые вообще нужны)
2. плохо написанный код по определению должен содержать места, которые выявит статический анализатор — ожидается, что чем их меньше, тем код лучше
3. и наоборот, чтобы написать очень плохой код так, чтобы статический анализатор ничего не заметил, это нужно постараться.

Однако, утверждение не может быть полностью правдивым по следующим причинам:
1. как бы хорош ни был анализатор, но он по своей природе не может выявить достаточно большой класс ошибок — как, например, логические ошибки
2. все еще грустнее в мире языков с динамической и\или слабой типизацией, например, таких, как PHP или JS — на то он и статический.
3. даже хороший статический анализатор будет выдавать ложные предупреждения в тех местах, где код корректен, но анализатору что-то там не понравилось; и это не плохо — не будет лишним как минимум обратить внимание на подозрительный код, а как максимум — переписать его (если это возможно) так, чтобы не было предупреждения, а вместе с тем и меньше недоумения у людей, которые будут этот код читать.

Учитывая эти (достаточно очевидные) моменты, что-то я очень сомневаюсь, что есть серьезные проекты, на которые не ругнулся бы С.А., даже лидер класса, такой, как PVS-Studio.
Впрочем, ТС это можно, свое дитя всегда самое красивое )
Формально Вы правы. Предположим, в одной программе все ошибки связаны с разыменование нулевого указателя. В другой программе, все ошибки, это опечатки. Далее предположим, что PVS-Studio плохо ищет опечатки и хорошо разыменование nullptr. Тогда да, сравнение некорректно.

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

P.S. Да, можно сказать, что мы почти не ищем, например, ошибки синхронизации. А качество проекта зависит от этого сильно. Однако, на практике, там где путают free с delete и сравниваю на равенство переменные (a==b==c==d), то скорее всего там и с синхронизацией всё будет плохо.
На самом деле статические анализаторы, в частности, PVS-Studio, очень полезны в поиске типовых ошибок, которые сам программист из-за усталости либо просто невнимания, а то и банально недостаточного опыта сам бы никогда не заметил. Выйти за пределы массива, забыть освободить память, скопипастить и забыть поменять все вхождения может даже гуру-программист, и такую ошибку просто в силу человеческого фактора может пропустить код-ревью. И тут большой вопрос, понижает ли опечатка качество кода, или все же за кошмарный стиль (пусть и без ошибок) надо бить сильнее?
Повторюсь, если статический анализ выявляет подозрительное место, пусть и правильное — но это же место может еще привести к другим ошибкам. Даже если все эти i+++++i понятны автору, то сторонний программист вполне вероятно тут споткнется.

Потому нужны и статические анализаторы, и код-ревью, и тестирование и однообразный стиль кода.
Вывод: где мы нашли меньше ошибок при написании статьи, там и код лучше :). Всё честно.
Давайте как пример рассмотрим NGINX, который Вы привели как пример качественного проекта, свидетельством чему было невыявление ошибок стат. анализом в 2014.
В 2017 вышла новость об устранении в нём уязвимости.
Я обратил внимание на то, как уязвимость была устранена:
+            if (size > NGX_MAX_OFF_T_VALUE - (end - start)) {
+                return NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            }
+
             size += end - start;

Это было устранение возможного переполнения. Я решил проверить как выводятся start и end, ведь переполнения во время арифметических действий для проверки возможности переполнения других арифметических действий для меня не являются новостью.
Я увидел следующую картину:
while (*p >= '0' && *p <= '9') { 
   if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) { 
        return NGX_HTTP_RANGE_NOT_SATISFIABLE; 
   } 
   start = start * 10 + *p++ - '0'; 
}

Проверка с выходом из функции должна была предотвращать возможное переполнение целого со знаком start, но вместо такого сложения
 start = start * 10 + (*p++ - '0'); 
было сделано такое
 start = (start * 10 + *p++) - '0'; 
Что приводит к возможности переполнения левой части, а учитывая знаковость start, это является неопределённым поведением, что не даёт гарантию компенсации последующим вычитанием '0'. Тогда я даже смог добиться некорректного поведения при компиляции похожего куска кода с помощью gcc с оптимизацией.
Это всё ставило под удар конечное утверждение об исправлении уязвимости, так как эта цепочка при определённых обстоятельствах могла привести к некорректности проверки.

Я сообщил о своей находке и через некоторое проблема была исправлена. Это было отрадно, но сама заплатка снова дала повод задуматься. Подобный функционал был разбросан по множеству перегруженных кодом функций. Эти куски не могли быть обобщены в одну функцию, которая могла быть подвергнута тщательному осмотру и тестированию из-за обилия неструктурного кода, мешающего провести декомпозицию. При таком подходе к написанию кода остаётся только гадать, сколько похожего кода было не затронуто исправлением, так как его трудней выявить. Более того, я обнаружил ещё недостатки, но уже утратил желание в этом участвовать — это стало походить на бесконечную историю.
А теперь вопросы:
  1. Способен ли подобные ошибки находить анализатор?
  2. Насколько качественный код NGINX?
  3. Насколько верно утверждение про связь невыявления ошибок стат.анализом и качеством?
Большой, красивый комментарий. Но мимо.

NGINX это качественный код? Да. И наш анализ это подтверждает.

Может в нём быть уязвимость? Да, может. И Ваш анализ это подтверждает.

Здесь нет противоречия. Всё дело в том, что NGINX это очень важный проект и его ОЧЕНЬ внимательно исследуют. И вполне естественно, что-то находят критические ошибки.

Однако, если подвернуть СТОЛЬ ЖЕ ТЩАТЕЛЬНОМУ анализу проект, который мы оценили невысоко, то там будет мрак и ужас с точки зрения безопасности. Просто такой анализ никто не будет делать, так как это не имеет практического смысла. Уязвимости в «калькуляторе» никому не интересны.
Вы проигнорировали моё упоминание бесконечной истории. Я не искал специально ошибки в NGINX, а просто потянул ниточку новости — и понеслось. Ошибки в NGINX не досадная случайность, а закономерность, вызванная подходом к написанию кода. Это именно некачественный код рыхлых, переутяжелённых функций.
Понимаете какая история — уже тот факт, что на ошибку, которая может, теорехтически, привести к каким-то там проблемам в какой-то там будущей версии компилятора, но которая существует только в исхожиках, но которая никак и нигде не проявляет себя в скомпилированной программе обратили внимание — уже является показателем качества.

В большинстве проектов подобное даже править не будут, потому что настоящих, проявляющихся в реальном мире, ошибок полно.
Это практическая ошибка, проявляющаяся на gcc. И показатель качества — это только качество кода, а не реакция на уведомления. Реакция — это, всё же, о другом
Это практическая ошибка, проявляющаяся на gcc.
Извините, но нет. Пока ошибки нет в бинарнике — это всё теория. «Похожий код», «если сменить настройки» — это всё теория.

Если ошибка есть в бинарнике — то это один уровень срочности, понятно, что нужно выпускать новую версию.

Если ошибка в исходнике, но в скомпилированном бинарнике её нет — то это принципиально другой уровень опасноcти.

И показатель качества — это только качество кода, а не реакция на уведомления.
Показатель качество — это, в некотором смысле количество «сферических CVE» (количнество CVE при условии, что все ошибки, заслуживающие статуса CVE таковой получают)

Судя по вашему описанию проблема, которую вы нашли не породила (и, главное, не могла породить) ни одного CVE.

Реакция — это, всё же, о другом
Реакция — это о том, есть ли у разработчиков ресурсы на то, чтобы реагировать не только на реальные CVE, но и на CWE и более слабые сигналы. Куда, увы и ах, относится и ваш пример…
Из чего Вы сделали вывод, что его не было в исполнимом коде?
Из вашего же сообщения: тогда я даже смог добиться некорректного поведения при компиляции похожего куска кода с помощью gcc с оптимизацией.

Зачем вам вместо банального objdump'а потребовался «похожий кусок кода», если и на оригинальном всё воспроизводилось?
Воспроизводилось что? Во время отдыха я прочитал новость, посмотрел код, нашёл неточность, вырвал кусок, собрал, увидел результат, описал его под новостью. Собирать и тестировать NGINX и даже официально уведомлять об ошибке никогда не входило в мои планы.
Тут Andrey2008 постоянно борется с таким пренебрежительным отношением к ошибкам, но оно, очевидно, неискоренимо даже в среде ценителей.
> было рационально проверить RT-Thread IoT OS, а не, например, игру.

Может быть наоборот стоить тестировать игру а не ОС. Многие разрабатывают игры (больше потенциальных клиентов) но не многие разрабатывают ОС.
На моём «умном» телевизоре сначала бОльшая часть приложений вылетала в определенный один момент, жалел что вообще купил «умный» телевизор, с ноутбуком по hdmi было лучше. После полугодового терпения ОС обновили, теперь в других местах проблемы, и вот ещё пол года идёт. Так что уж лучше кривое приложение я сразу после установки удалю, а ОС не должна давать приложениям повод вести себя некорректно.
Про игры мы и так регулярно пишем (см. раздел «Разработка игр»). Странно приурочить к выходу версии для Embedded ещё одну такую статью. :)
>> популяризировать методологию статического анализа в целом

Конечно же, это не так. В «целом» ничего похожего на методологию не популяризуется, нет сравнений с другими решениями анализа. Вообще, про «методологию» не так много информации, чтобы можно было сравнить с другими методологиями.
В 99% показываете результат анализа, описание некоторых правил анализа, но полную методологию скрываете.
В этом ничего плохого, ноу-хай и все такое, но не стоит лукавить, что вы популяризируете методологию.
Эээ…

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

Быть может Вы путаете методологию и реализацию? Вот в случаях обсуждения реализации можно говорить о сравнении с другими решениями и о отсутствии описания в наших статях деталей этой самой реализации.
А версия PVS для Rust, D-Lang и C-- имеется?
(собираюсь один из этих языков изучить)
Поддерживается анализ: C, C++, C#. В данный момент работаем над стандартом MISRA C и языком Java. Дальше планы пока не утверждены, так как Java это очень большое направление.

Для MISRA на Википедии такой список анализаторов приведен, что еще один среди них затеряется. Ява конечно смотрится более перспективной.

А что делать, хотят… :)
А анализатор предполагается самого java-кода или java-байткода? Во втором случае он будет применим ко всем языкам компилируемым в java-байткод.
Java-кода, конечно.
Просто FindBugs например именно байткод анализирует.
В байткоде мало, чего можно найти. Возможно, мы совместим эти технологии для повышения точности и доп. фич, но основой анализа будут исходники.

Для Раста уже есть анализатор (clippy), да и сам язык такой, что накосячить в разы сложнее, чем в С

Круто сделали редизайн сайта :) Планируете в ближайшее время новые статьи по жирным проектам на С#/Java?
Спасибо. По Java точно планируем.
Я попытался использовать ваш продукт, но у него как-то плохо с дистрибьюцией.

apt install pvsstudio
E: Unable to locate package pvsstudio

Я понимаю, что у вас есть Глубокие Причины, почему вас нет в списке пакетов, но… всё равно неудобно.
E: Unable to locate package pvs-studio
Нас нет в списке стандартных пакетов, если быть точным. Следовательно, подключив наш репозиторий, анализатор успешно установится и будет обновляться. Смотрите страницу "Установка и обновление PVS-Studio в Linux".
С точки зрения дистрибьюции, отсутствие в репозиториях Дебиана — большой минус.
Пакет несвободный, с чего ему там быть.
Дело не в этом. Репозитории на своем ресурсе намного проще и быстрее обновлять. В конечном итоге наш репозиторий оказывается удобнее нашим клиентам, чем если бы по полгода-год мы тратили на обновление в официальном репозитории.
А, его нет в main? Ну, тогда вообще плохо. Ни сырцов ни скачать, ни свою версию не поправить… Проприетарщина, одним словом.
Прям перед Вашим постом прочитал комментарий. Кто-то из Вас точно из Австралии)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий