Pull to refresh

Comments 87

Кроме явных ошибок при программировании есть еще плохие/запрещенные практики: посмотрите на инструменты checkstyle, PMD, findbugs. Ну и было бы очень хорошо, если это будет pure-java решением и не придется тащить платформо-зависимые бинарники.
Плохие практики и код-стайл не рассматриваются для реализации и в других наших анализаторах. Такое видение продукта: вменяемое кол-во предупреждений на проекте с максимальным процентом найденных реальных ошибок.

Кстати, на коде Идеи у вас вменяемое количество предупреждений? :-)

Да, срабатываний мало, особенно относительно других проектов :)

Ничего себе! У нас только dataflow выдаёт больше 10000 предупреждений, а все включённые инспекции на всём коде Идеи — около 200000. Что с ними делать — абсолютно непонятно :-D

Предупреждение != ошибка. Как я понимаю, большинство из этих предупреждений шум (фиксить код смысла нет) и полезное тонет в них. Мы очень опасаемся такой ситуации и внимательно подходим к отбору диагностик.

Спасибо что вы наконец пришли в java мир, как всегда приятно читать ваши статьи.

Вы на проект SonarQube смотрели? Там только для Java больше 1700 инспекций...


Ну а если вы таки сможете придумать что-то дополнительно к уже имеющемуся там, то имеет смысл написать плагин для SonarQube, т.к. он является стандартом де-факто в корпоративной среде. Уж коли вы на корпоративный рынок целитесь...

SonarQube мы смотрели внимательно и уверены, что сможем реализовать более качественные диагностики для поиска ошибок в Java коде. Да, в SonarQube много диагностик на тему «плохого запаха кода». Мы же ориентированы на поиск именно ошибок. Поэтому, мы скорее дополняем его, а не конкурируем с ним. Java анализатор будет встраиваться в SonarQube, как мы уже делаем это для C++ и C#. Некоторые наши клиенты как раз используют PVS-Studio как плагин к SonarQube.
Там только для Java больше 1700 инспекций...

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

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


Так что мне будет очень любопытно понаблюдать за развитием событий :-)


Больше статик анализа большого и разного :-)

вы вступаете на рынок, на котором тема статического анализа прорабатывается давно и плотно.
Ну хоть в какой-то сфере интересна эта тема :D А то сейчас дописываю статью про один игровой движок (С++). Там такое качество кода, что статья получилась крайне эмоциональной.
Кстати, непонятно откуда взялось 1700 инспекций для Java. В SonarJava реализовано 440 Rules, из которых 315 это Code Smells.

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

А… Там не только собственные правила от SonarQube, но и от FindBugs, Checkstyle и PMD. Так что похоже тут наши цифры и разошлись :-)

Нас по-разному сравнивали с конкурентами, но так совсем не честно)
К слову, пример вполне реальной ошибки, которую нашел наш анализатор в самом проекте SonarQube:

V6029 Possible incorrect order of arguments passed to method: 'parent', 'profile'. InheritanceActionTest.java 254:
  private void setParent(QProfileDto profile, QProfileDto parent) {
    ruleActivator.setParentAndCommit(dbSession, parent, profile);
  }


RuleActivator.java
 public List<ActiveRuleChange> setParentAndCommit(
   DbSession dbSession, 
   QProfileDto profile,
   @Nullable QProfileDto parent) {
    .... 
}
Или вот еще например:
private void setUpdatedAtFromDefinition(@Nullable Long updatedAt) {
    if (updatedAt != null && updatedAt > definition.getUpdatedAt()) {
      setUpdatedAt(updatedAt);
    }
  }

 private void setUpdatedAtFromMetadata(@Nullable Long updatedAt) {
    if (updatedAt != null && updatedAt > definition.getUpdatedAt()) {
      setUpdatedAt(updatedAt);
    }
  }

Что-то мне подсказывает, что здесь скопипастили и забыли во втором случае поменять definition на metadata.
UFO just landed and posted this here
На таком варианте тоже будет срабатывание. Мы используем эвристику для определения «похожести».
Ещё много работы и определённости нет. Надеемся, что осенью.
Подозреваю будет верещать возможными NPE в проекте со спрингом видя чтото вроде
@Autowired
private SomeService someService;
Сталкивались с подобным, когда разрабатывали maven-плагин:
@Parameter(defaultValue = "${reactorProjects}", readonly = true)
private List<MavenProject> reactorProjects;

Так что стараемся учитывать подобный код.
А для простых смертных будет доступно? А то я слышал, что вам нужно куда-то на почту писать, чтобы получить цены / бесплатную копию.
Возможности пробного запуска, триальный и бесплатный режимы будут перенесены из C++/C# анализаторов. Если Вы с ними не знакомы, то вкратце: попробовать полноценную версию анализатора сможет любой желающий.
Вы не планируете прийти в мир php? Тем более что он в некоторым смысле родственник java.
UFO just landed and posted this here
По моему, влияние Java на PHP меньше разве что влияния C на C++.
По моему php для бэкэнда и javascript для фронтэнда — просто удобная связка например для того кто делает все сам. На одной волне.
Не хочу поднимать холивар, но почему тогда уж не fullstack javascript, если все равно делать и то, и то?
Тоже не хочу холиваров. Не совсем ясно я выразился. Бекэндом сейчас не занимаюсь, но именно работа на PHP заставила меня пересмотреть мое отношение к javascript. В некоторых моментах дисциплинировало и открыло некоторые возможности о которых я не подозревал. Сорри что не по теме.
Добрый день.

Есть ли идеи использования нейронных сетей для поиска ошибок в коде?
Нет. И не понятно, где собрать столько ошибок по каждому виду дефекта, чтобы её обучить.
reinforcement learning. Пускай нейросеть меняет маленькие кусочки кода и пытается компилировать проект.

Так можно ненароком скомпилировать нечто такое, что человек никогда бы не написал (голос ИИ за кадром: МУАХАХАХАХАХА)

А когда ИИ закончит с улучшением кода, начнёт брать таски из баг-трекера…
А потом ИИ поймет, что корень всех багов — в нелепых кусках мяса перед монитором…

В таком случае НС максимум повторит компилятор.
Ошибки в логике компилятор не ищет.

Молодцы, что статью написали! И жалко, что вас на конференцию не взяли (я рекомендовал брать, но не послушали).


Да, FABA — это был проект в JetBrains, и он интегрирован в Идейку. Чистоту методов тоже иногда умеем выводить. И контракты вида null->false. И по сорцам умеем иногда, не только по байткоду. Причём по сорцам на лету в процессе редактирования.


Вопрос: при сравнении строк вы различаете равенство по ссылке и по контенту? str1.equals(str2) && str1 != str2 вы подсветите (ошибочно) как всегда ложное или нет?

Да такое мы различаем, благодаря тому, что dataflow взяли из C++. Там ведь возможна аналогичная ситуация:
  int *ptr1 = ....;
  int *ptr2 = ....;
  if (*ptr1 == *ptr2 && ptr1 != ptr2) { .... }

Если в двух словах, то виртуальные значения для ссылок в Java, это наши виртуальные значения для указателей из C++. А виртуальное значение для указателя может, в свою очередь, содержать «boxed» значение (например целого числа, строки, и т.п.).
Ну и соответственно, в одном случае сравниваются виртуальные значения строк, а в другом указателей ссылок.
В Enterprise вам придется конкурировать не с SonarQube а с HP Fortify и Veracode. Мне приходилось сталкиваться с обоими системами. По ощущениям — HP Fortify более продвинутый. К примеру, если создается из кусков строк SQL выражение и выполняется просто через statement, то Veracode укажет это как SQL injection (и это может оказаться false positive), а Fortify проанализирует откуда берутся эти куски и, если там нет user input (в любом виде), то SQL injection не будет обнаружен. Если вы будете escap'ить сами user input чтобы избежать SQL injection, то Fortify это может понять, а Veracode — нет.
Далее — Veracod сканирует jar/war/ear файлы и ему не нужны исходники. Fortify встраивается в билд процесс (у нас был maven). Из этого можно сделать выводы, что Veracode просто разбирает Java bytecode, а Fortify получает AST (abstract syntax tree) и уже работает с ним. То есть обе системы не работают напрямую с исходниками и нет необходимости осуществлять синтаксический анализ исходников. По моему мнению это правильный подход, тем более что Java bytecode хорошо описан в спецификации. Я писал программу, которая его разбирает и дошел до команд виртуальной машины. По ощущениям, структура скомпилированного Java class файла достаточно логичная и понятная.
По поводу того, как используется сканер — приложение обязательно должно сканироваться перед релизом и релизить можно только приложения без critical и very height уязвимостей (это идеал, на практике, конечно, бывает по разному). К упомянутым типам уязвимостей относятся XSS, SQL injection, hardcoded passwords. На code smells всем наплевать при сканировании. То есть сканирование — это выявление уязвимостей, которые могут повлиять на безопасность системы. Качество кода не является сколь-нибудь важным на данном этапе.
И еще одно — не знаю как сейчас устроено у HP Fortify, но Veracode предоставляет сервис: вы закачиваете артифакты, Veracode их сканирует, вы получаете отчет (в web системе), в котором указаны найденные проблемы. У вас есть возможность связаться с сотрудниками Veracode, чтобы обсудить найденные уязвимости и пометить их как false positive (при необходимости). То есть это целая инфраструктура, которая не заканчивается на сканере.
Спасибо за подробный комментарий и информацию.

На уровне байткода анализировать джаву — довольно тупиковый путь. Я писал свой анализатор на байткоде. Некоторые проблемы в принципе не увидишь. Надо быть как можно ближе к исходникам.


Я вот даже не уверен, что автоматическое удаление скобок в Spoon — это хорошая идея. Например, a << 16 + b похоже на ошибку: приоритет сложения выше, чем сдвига, а выглядит так будто автор забыл про это. С другой стороны, a << (16 + b) уже выглядит сознательным решением, и тут предупреждать не надо. Если есть дерево без скобок, эту разницу не увидишь. Даже комментарии в коде и отступы очень важны для статического анализа.

Мы в таких отдельных случаях смотрим оригинальный код (spoon запоминает позиции для элементов).
Я думаю это просто разные модели представления исходного кода. Дейсвтительно, комментарии, отступы, скобки важны для детектирования недостатков, нарушений стиля кода. В то же время они только мешаются во время анализа потоков данных или при использовании еще более глубоких типов анализа (абстрактная интерпретация). Для последних байт-код будет очень кстати.

Как вариант, можно анализировать на разных уровнях. В компиляторном мире, как правило, даже разделяют понятия: дерево разбора (Parse Tree) и абстрактное синтаксическое дерево (AST). Первое вообще может быть преобразовано обратно в код символ-в-символ (full fidelity). Второе не содержит незначимые узлы.

У нас в Идейке parse tree с full fidelity, конечно, но это не сильно усложняет потоковый анализ. Конечно, у нас и вычисление типов, и резолв ссылок сделан. В байткоде с этим проще, но и свои минусы есть — erasure. Восстановить generic-сигнатуру бывает очень сложно (эту задачу решают декомпиляторы). С байткодом, кстати, ещё большой минус — привязать предупреждение к конкретному элементу исходника. Там только номера строк есть, если отладочную инфу генерировали. Иногда это сильно усложняет понимание, где же ошибка.

И еще одно — в Java есть куча Web framework'ов с которыми Veracode умеет работать. И если для JSP еще можно как-то выкрутиться, скомпилировав в Java код, а дальше анализировать как pure java, то все остальное нужно реализовывать специфичным для данного framework'а образом.

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

C# анализатор слабее, чем C++. Со временем мы мечтаем улучшить C# анализатор, начав использовать в нём ядро C++, как это мы сразу делаем в Java-анализаторе. Плюс планируем (когда освободятся силу после Java) подобавлять в C# анализатор новые диагностики.

А можете еще раз в двух словах (для идиотов) пояснить, что означает использовать С++ ядро для java-анализатора? В статье это как-то очень замысловато описано. И почему не получилось это сделать для С# анализатора?

А можете еще раз в двух словах (для идиотов) пояснить, что означает использовать С++ ядро для java-анализатора? В статье это как-то очень замысловато описано.
Как-же в двух словах то объяснить… Целая статья для этого понадобилась. :)

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

Спасибо, так понятнее. Ну, видимо, набив шишек на С#, вы теперь нормально реализуете Java, а потом может и С# переработаете под общую схему. Эксперимент с С# был интересный.

Если еще проще, то мы взяли dataflow анализатор и еще некоторый функционал из C++ анализатора и прикрутили его к Java анализатору (почти как библиотеку).
Про C# я не знаю наверняка, но думаю что на тот момент и инфраструктура C++ анализатора тоже не позволила бы так просто перенести что-либо в C#.
Плагин для IDEA разрабатывается с учетом Rider-а и C#?
Плагин для IDEA достаточно универсален. Возможность запуска PVS-Studio в CLion и Rider будет исследоваться в другой задаче.
Хотелось бы, что его можно было использовать и в CLion и в Rider. Надеюсь эта задача не уйдет в долгий ящик…
Nice! Спс, что уведомили) Нужно пробовать. Офигеть, почти два года прошло… И это хорошо, что плагин был достаточно универсальным) Боюсь представить сроки, если бы пришлось с нуля писать…
«В статическом анализе программ многие себе могилу нашли» — © Шелехов В.И., с.н.с. ИСИ СО РАН, занимался статическим анализом как наукой более 20 лет, пытался продавать статический анализатор для Java в начале нулевых :). Хотя конечно есть весьма успешные статические анализаторы.
Посмотрел несколько примеров- та же IDEA так же находит ошибки.
Вы приходите в мир, где статических анализаторов масса. Покажите примеры ошибок, которые не находят существующие популярные решения. До этого- мысль только «ещё одни решили сделать революцию, а вышел пшик».

В посте пару ошибок из самого intellij.

Исходники PV просто недоступны для анализа :)

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

Это ни о чём не говорит. Идейка в сорцах Идейки находит двести тысяч предупреждений. В том числе и те, которые в посте есть. Просто не всегда доходят руки их исправить.

Это тут ни при чём. Там и реальных проблем полно, десятки тысяч, и можно сделать профиль инспекций, который только реальные проблемы будет показывать. Особенно с nullability много. Это механически не исправишь, там в каждом месте смотреть надо.

Ой, тогда я просто не могу немножко не потроллить. Прошу прощение, я не со зла, но не могу удержаться. :)

Т.е. создан статический анализатор кода, которым невозможно пользоваться? Даже сами разработчики не могут настроить его, чтобы использовать результаты его работы в своём проекте?

Вот у нас вывод PVS-Studio на PVS-Studio чистый. И если где-то накосячили, то нам на почту приходит только одно-два предупреждения. :)
Почему невозможно? Возможно. Во-первых, у нас кода нереально больше, чем у вас. У нас не статический анализатор, а IDE, которая поддерживает уйму языков и миллион фич вроде интеграции с Git, Docker и чёрт знает что ещё. Во-вторых, я, например, никогда не коммичу жёлтый код. В новом коде от меня варнингов нет. Если я редактирую существующий код, я по возможности заодно исправляю варнинги в нём. Многие поступают так же.

Ну и вы же сами зачем-то поддерживаете режим «показать только свежие предупреждения». По вашей логике, если эта фича востребована, значит, вашим анализатором тоже невозможно пользоваться ;-)
Ну и code smells — понятие растяжимое. Пример метода equal из Hive в этой статье — вполне себе code smell. Условие избыточно и всегда истинно, но не приводит ни к каким проблемам. Если его убрать, поведение метода не меняется ни при каких входных данных. Так что это не баг.
Вы точно про этот пример? Здесь перепутали && и ||.
String colOrScalar1 = tdesc[4];
....
if (colOrScalar1.equals("Col") &&
    colOrScalar1.equals("Column")) {
    ....
} else if (colOrScalar1.equals("Col") &&
           colOrScalar1.equals("Scalar")) {
    ....
} else if (colOrScalar1.equals("Scalar") &&
           colOrScalar1.equals("Column")) {
    ....
}

Такой паттерн это же явно баг.

Нет, я про другой пример. Нумеруйте их что ли, чтобы ссылаться можно было =)


public static boolean equal(byte[] arg1, final int start1,
                            final int len1, byte[] arg2,
                            final int start2, final int len2) {
    if (len1 != len2) { // <=
      return false;
    }
    if (len1 == 0) {
      return true;
    }
    ....
    if (len1 == len2) { // <=
      ....
    }
}
Так, — чем чёрт не шутит, — и анализатор на Java перепишите)
Так ждал от вас статический анализатор для Java, но уже перешел на Kotlin.
Буду ждать дальше :)

В статье же всё сказано. Нет, не байткод.


И разница, кстати, большая. Вы огребёте большое количество ложных сработок на котлиновском байткоде, если возьмётесь его анализировать джавовским анализатором байткода. Я пробовал.

Не в тему статьи, но кто-то пользуется статическими анализаторами SQL & PL/SQL? Можете опытом поделиться?

Использовал sqlcodeguard + sonar-tsql-plugin
Логика tsql была без тестов — проект легаси с человеко-годами техдолга. Масштабы бедствия менеджменту и команде показал, но адекватных действий так и не дождался. Разработчики хранимок так и не использовали этот подход в процессе разработке.

Для PL/SQL мой бывший коллега скрещивал статический анализатор Toad c Sonar, чтобы сэкономить деньги компании на платном плагине. На других проектах максимум что использовали DBA — это юнит тесты для хранимок в Oracle, без статического анализа кода.
Спасибо, Игорь! Пока опыта тоже не густо — разработчикам это не интересно…
Хотя когда находишь что-то при случайном просмотре кодовой базы, некоторые интересуются, каким анализатором пользуюсь…
Sign up to leave a comment.