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

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

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

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

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

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

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


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

>
>
>
Статический анализ кода Mozilla Thunder…

Статический анализ кода Mozilla Thunderbird с помощью PVS-Studio

24 Сен 2015

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

0347_Thunderbird_ru/image1.png

Почтовый клиент Mozilla Thunderbird

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

Об анализаторе PVS-Studio

PVS-Studio - статический анализатор кода для С и С++ программ. PVS-Studio предоставляется как плагин к системе разработки Visual Studio, но может быть использован и через утилиту Standalone. Эта утилита имеет функцию мониторинга, которая отслеживает вызовы компилятора и передает нужные файлы анализатору. Таким образом PVS-Studio не зависит от сборочной системы проекта.

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

Сборка и проверка Thunderbird

Mozilla имеет свою собственную сборочную систему. Инструкцию, описывающую основные шаги для сборки проекта можно найти здесь. Сама сборка сделана максимально удобно для пользователя. Mozilla предоставляет бинарный инсталлятор всех необходимых для установки под windows утилит, например, 7zip, msys, mercurial и т.п.

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

Предупреждения анализатора

Thunderbird является крупным проектом и использует множество сторонних библиотек. Большинство предупреждений пришлось именно на их код. Для статьи я постарался отсеять эти предупреждения и оставить только те, которые выдавались на исходный код почтовой программы.

Кроме того, для описания багов в проектах Mozilla есть страница с описанием ключевых слов. Среди них можно найти такие как coverity, klocwork, valgrind и clang-anazyler. Похоже, что эти средства анализа кода уже используются в Mozilla. Так что будет интересно посмотреть на то, что не заметили эти анализаторы.

Подозрительные условия

Предупреждение PVS-Studio: V501 There are identical sub-expressions 'aStatus == NS_ERROR_OFFLINE' to the left and to the right of the '||' operator. nsdocshell.cpp 7606

nsresult
nsDocShell::EndPageLoad(nsresult aStatus, ....)
{
  if(....)
  {
    ....
  }
  else if (aStatus == NS_ERROR_NET_TIMEOUT ||
           ....
           aStatus == NS_ERROR_OFFLINE ||
           aStatus == NS_ERROR_MALWARE_URI ||
           aStatus == NS_ERROR_PHISHING_URI ||
           aStatus == NS_ERROR_UNWANTED_URI ||
           aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
           aStatus == NS_ERROR_REMOTE_XUL ||
           aStatus == NS_ERROR_OFFLINE ||
           ....)
}

Этот код содержит лишнюю проверку "NS_ERROR_OFFLINE". Список значений, на которые нужно проверить переменную 'aStatus' большой, поэтому легко можно ошибиться и случайно продублировать проверку. Вторым вариантом может быть то, что программист после копирования вставлял одну и ту же строчку, чтобы не переписывать одинаковую часть, и забыл поменять название константы "NS_ERROR_OFFLINE". В таком случае в коде не хватает одной нужной проверки.

Предупреждение PVS-Studio: V590 Consider inspecting the 'type != (1) && type == (2)' expression. The expression is excessive or contains a misprint. nswindowsregkey.cpp 313

#define REG_SZ        ( 1 ) 
#define REG_EXPAND_SZ ( 2 )
#define REG_MULTI_SZ  ( 7 ) 

NS_IMETHODIMP
nsWindowsRegKey::ReadStringValue(const nsAString& aName, 
                                       nsAString& aResult)
{
  ....
  if (type != REG_SZ && 
      type == REG_EXPAND_SZ && 
      type == REG_MULTI_SZ) 
  {
    return NS_ERROR_FAILURE;
  }
  ....
}

Условие "type == REG_EXPAND_SZ && type == REG_MULTI_SZ" всегда ложно, так как одна переменная не может иметь два значения одновременно. Как результат, функция никогда не вернет статус ошибки NS_ERROR_FAILURE.

Предупреждение PVS-Studio: V616 The 'eBorderStyle_none' named constant with the value of 0 is used in the bitwise operation. nswindow.cpp 2318

enum nsBorderStyle 
{
  eBorderStyle_none = 0,
  ....
}  

NS_IMETHODIMP nsWindow::SetNonClientMargins(....)
{
  if (!mIsTopWidgetWindow ||
      mBorderStyle & eBorderStyle_none)
    return NS_ERROR_INVALID_ARG;
  ....
}

При проверке условия используется константа со значением 0, которая участвует в побитовой операции "И" с переменной. Результатом операции, разумеется, тоже будет ноль. Таким образом условие не зависит от переменной "mBorderStyle".

Подобное предупреждение:

  • V616 The 'nsIDocShell::BUSY_FLAGS_NONE' named constant with the value of 0 is used in the bitwise operation. presentationcallbacks.cpp 105

Предупреждение PVS-Studio: V646 Consider inspecting the application's logic. It's possible that 'else' keyword is missing. nsnativethemewin.cpp 924

nsresult 
nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, 
                                       uint8_t aWidgetType, 
                                       int32_t& aPart, 
                                       int32_t& aState)
{
  ....
{
  ....
  if (!aFrame) {
    aState = TS_NORMAL;
  } else {
    if (GetCheckedOrSelected(aFrame, !isCheckbox)) {
      inputState = CHECKED;
  } if (isCheckbox && GetIndeterminate(aFrame)) {
      inputState = INDETERMINATE;
  }
  ....
}   ....
}

Возможно, что перед последним "if" пропущено слово else. Код к текущем виде подразумевает, что могут выполниться оба условия if, и тогда значение "CHECKED" в переменной "inputState" будет изменено на "INDETERMINATE". Если бы в этом коде выполнялось либо одно условие, либо другое, то логичней было бы использовать "if - else", как во внешней конструкции.

Еще одна похожая конструкция располагается здесь:

  • V646 Consider inspecting the application's logic. It's possible that 'else' keyword is missing. debugger.cpp 4794

Предупреждение PVS-Studio: V713 The pointer mHTMLEditor was utilized in the logical expression before it was verified against nullptr in the same logical expression. nshtmleditrules.cpp 6593

nsHTMLEditor* mHTMLEditor;

nsresult
nsHTMLEditRules::SplitParagraph(...)
{
  if (mHTMLEditor->IsTextNode(child) || 
      !mHTMLEditor ||
      mHTMLEditor->IsContainer(child))
  ....
}

Функция "SplitParagraph" в своей проверке содержит ошибочный порядок аргументов. Если в данном коде указатель mHTMLEditor будет нулевым, то перед обнаружением этого он уже будет разыменован, что приведет к неопределенному поведению. Чтобы исправить код, нужно поменять местами "!mHTMLEditor" и "mHTMLEditor->IsTextNode(child)".

Две аналогичных ошибки располагаются здесь:

  • V713 The pointer mHTMLEditor was utilized in the logical expression before it was verified against nullptr in the same logical expression. nshtmleditrules.cpp 7392
  • V713 The pointer mHTMLEditor was utilized in the logical expression before it was verified against nullptr in the same logical expression. nshtmleditrules.cpp 7413

Предупреждение PVS-Studio: V522 Dereferencing of the null pointer 'aStyleValues' might take place. sdnaccessible.cpp 252

STDMETHODIMP sdnAccessible::get_computedStyle(
                   BSTR __RPC_FAR* aStyleProperties,
                   BSTR __RPC_FAR* aStyleValues,
                   unsigned short __RPC_FAR* aNumStyleProperties)
{
  if (!aStyleProperties || aStyleValues || !aNumStyleProperties)
    return E_INVALIDARG;
  ....
  aStyleValues[realIndex] = ::SysAllocString(value.get());
  ....
}

Как говорится, заметь проказника.

0347_Thunderbird_ru/image2.png

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

Предупреждение PVS-Studio: V547 Expression is always false. Probably the '||' operator should be used here. nsmsgdbview.cpp 3014

class NS_NO_VTABLE nsMsgViewCommandType 
{
  enum 
  {
    ....
    junk = 27,
    unjunk = 28,
    ....
  };
};

nsresult nsMsgDBView::
ApplyCommandToIndices(nsMsgViewCommandTypeValue command, ....)
{
  ....
  if ((command == nsMsgViewCommandType::junk) &&
      (command == nsMsgViewCommandType::unjunk))
  ....
}

Код, соответствующий блоку if никогда не будет выполняться, поскольку переменная command не может одновременно иметь два значения. Более логичным здесь кажется использование оператора "ИЛИ" - "||".

Проблемы с указателями

Предупреждение PVS-Studio: V579 The HashBytes function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the second argument. nsdisplaylist.h 929

struct AnimatedGeometryRootLookup
{
  ....
  PLDHashNumber Hash() const 
  {
    return mozilla::HashBytes(this, sizeof(this));
  }
  ....
}

Анализатор счел подозрительным, что в функцию "HashBytes" первым аргументом передается указатель, а вторым - размер указателя. Если поискать в исходных файлах по названию функции, то в файле "hashfunctions.h" можно найти следующий комментарий:

/* Utilities for hashing. */

/*
 * This file exports functions for hashing data down 
 * to a 32-bit value, including:
   ....
 * - HashBytes     Hash a byte array of known length.
   ....
 */

Комментарий подсказывает, что вторым аргументом должен быть размер объекта, располагающегося по указателю. Скорее всего правильный код должен выглядеть так:

return mozilla::HashBytes(this, sizeof(*this));

Перейдем к следующему предупреждению.

Предупреждение PVS-Studio: V611 The memory was allocated using 'new' operator but was released using the 'free' function. Consider inspecting operation logics behind the 'instanceData' variable. nptest.cpp 971

NPError NPP_New(....)
{
  ....
  InstanceData* instanceData = new InstanceData;
  ....
  free(instanceData);
  ....
}

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

Да и вообще так делать нельзя. Подобный код приводит к неопределенному поведению программы.

Предупреждение PVS-Studio: V614 Potentially uninitialized pointer 'hOldFont' used. progressui_win.cpp 168

static void InitDialog(....) 
{
  ....
  HFONT hInfoFont, hOldFont;
  hInfoFont = (HFONT)SendMessage(hWndInfo, WM_GETFONT, 0, 0);

  if (hInfoFont)
    hOldFont = (HFONT)SelectObject(hDCInfo, hInfoFont);
  ....
  if (hOldFont)
    SelectObject(hDCInfo, hOldFont);
  ....
}

Если функция "SendMessage" вернет ноль, то результат следующей проверки будет false, а значит переменная hOldFont не будет инициализирована. Переменная будет иметь случайное значение, которое может быть не равно нулю. Если оно не равно 0, то это случайное значение будет передано в функцию SelectObject.

Еще одна подобная ситуация может возникнуть здесь:

  • V614 Potentially uninitialized pointer 'queryD3DKMTStatistics' used. gfxwindowsplatform.cpp 206

Ошибки copy-paste

Предупреждение PVS-Studio: V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 1060, 1062. nsstylestruct.cpp 1060

nsStyleClipPath::nsStyleClipPath(const nsStyleClipPath& aSource)
{
  if (aSource.mType == NS_STYLE_CLIP_PATH_URL) {
    SetURL(aSource.mURL);
  } else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
    SetBasicShape(aSource.mBasicShape, aSource.mSizingBox);
  } else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
    SetSizingBox(aSource.mSizingBox);
  }
}

Блок "if - else if" содержит повторяющуюся проверку на равенство, вызванную copy-paste методом. Это означает, что последняя часть кода, соответствующая второй проверке на "NS_STYLE_CLIP_PATH_SHAPE", никогда не будет выполнена.

0347_Thunderbird_ru/image3.png

Предупреждение PVS-Studio: V523 The 'then' statement is equivalent to the 'else' statement. mozspelli18nmanager.cpp 34

NS_IMETHODIMP 
mozSpellI18NManager::GetUtil(mozISpellI18NUtil **_retval, ....)
{
  ....
  nsAutoString lang;
  ....
  if(lang.EqualsLiteral("en"))
  {
    *_retval = new mozEnglishWordUtils;
  }
  else
  {
    *_retval = new mozEnglishWordUtils;   
  }
  NS_IF_ADDREF(*_retval);
  return NS_OK;
}

Анализатор обратил внимание на то, что блокам if и else соответствуют одинаковые действия. Это может быть ошибкой при копировании, лишним условием или просто недописанным кодом. Так или иначе в данном виде условие не имеет смысла.

Еще несколько подобных ошибок:

  • V523 The 'then' statement is equivalent to the 'else' statement. jemalloc.c 6504
  • V523 The 'then' statement is equivalent to the 'else' statement. nsnativethemewin.cpp 1007
  • V523 The 'then' statement is equivalent to the 'else' statement. msgmapihook.cpp 677

Неопределенное поведение

Предупреждение PVS-Studio: V595 The 'aParent' pointer was utilized before it was verified against nullptr. Check lines: 511, 518. nsgenericdomdatanode.cpp 511

#define NS_ADDREF(_ptr) \
  (_ptr)->AddRef()

nsresult
nsGenericDOMDataNode::BindToTree(nsIContent* aParent, ....)
{
  ....
  ShadowRoot* 
  parentContainingShadow = aParent->GetContainingShadow();
  ....
  if (aParent) 
  {
    if (!GetParent()) 
    {
      NS_ADDREF(aParent);
    }
    mParent = aParent;
  }
  ....
}

Проверка указателя "aParent" подсказывает, что он может быть нулевым. Это значит, что при первом его разыменовании, которое происходит до проверки, мы рискуем получить неопределенное поведение.

Предупреждение V595 является одним из самых распространенных среди проверяемых проектов, и Thunderbird - не исключение. Всего анализатор выдал 95 предупреждений, касающихся непосредственно кода Thunderbird.

Предупреждение PVS-Studio: V610 Undefined behavior. Check the shift operator '<<'. The left operand '~0L' is negative. nsprotocolproxyservice.cpp 336

static void
proxy_MaskIPv6Addr(PRIPv6Addr &addr, uint16_t mask_len)
{
  ....
  addr.pr_s6_addr32[3] = PR_htonl(
    PR_ntohl(addr.pr_s6_addr32[3]) & (~0L << (128 - mask_len)));
  ....
}

Когда один из параметров смещения влево является отрицательным числом, поведение не определено. Вот что сказано об этом в стандарте:

The shift operators << and >> group left-to-right. shift-expression << additive-expression, shift-expression >> additive-expression

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. 1. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand. 2. ... If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1*2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined. ...

Еще 3 случая неопределенного поведения:

  • V610 Undefined behavior. Check the shift operator '<<'. The left operand '~0L' is negative. nsprotocolproxyservice.cpp 341
  • V610 Undefined behavior. Check the shift operator '<<'. The left operand '~0L' is negative. nsprotocolproxyservice.cpp 347
  • V610 Undefined behavior. Check the shift operator '<<'. The left operand '~0L' is negative. nsprotocolproxyservice.cpp 354

Предупреждения с функциями

Предупреждение PVS-Studio: V597 The compiler could delete the 'memset' function call, which is used to flush 'ctx' object. The RtlSecureZeroMemory() function should be used to erase the private data. gmploader.cpp 166

bool GMPLoaderImpl::Load(....)
{
  SHA256Context ctx;
  ....
  // Overwrite all data involved in calculation as it could 
  //potentially identify the user, so there's no chance a GMP
  //can read it and use it for identity tracking.
  memset(&ctx, 0, sizeof(ctx));
  ....
}

Здесь анализатор обратил внимание, что вызов функции 'memset' может быть удалён. Так как переменная 'ctx' в дальнейшем не используется, компилятор имеет полное право при оптимизации убрать вызов "memset". В Windows можно воспользоваться функцией "RtlSecureZeroMemory".

Предупреждение PVS-Studio: V530 The return value of function 'getenv' is required to be utilized. nswindowswmain.cpp 134

int wmain(int argc, WCHAR **argv)
{
  ....
  // Force creation of the multibyte _environ variable.
  getenv("PATH");
  int result = main(argc, argvConverted, _environ);
  ....
}

Здесь мы имеем дело с вызовом функции "getenv", результат которой не используется и даже не записывается в переменную. Вот как описана эта функция на сайте cplusplus.com.

Retrieves a C-string containing the value of the environment variable whose name is specified as argument. If the requested variable is not part of the environment list, the function returns a null pointer.

Использование "getenv" в таком виде бессмысленно и только смущает при чтении кода.

Прочие предупреждения

0347_Thunderbird_ru/image4.png

Предупреждение PVS-Studio: V609 Divide by zero. Denominator range [0..8]. ionbuilder.cpp 10922

static inline size_t UnboxedTypeSize(JSValueType type)
{
  switch (type) {
    ....
  default: return 0;
  }
}

MInstruction*IonBuilder::loadUnboxedProperty(size_t offset, 
                              JSValueType unboxedType, ....)
{
  size_t index = offset / UnboxedTypeSize(unboxedType);
  ....
}

Так как функция "UnboxedTypeSize" может вернуть ноль, то потенциально мы имеем дело с делением на ноль. Если в функцию "UnboxedTypeSize" будет передан новый тип, то она вернёт дефолтное нулевое значение, что приведёт к возникновению исключительной ситуации. Лучше перестраховаться и добавить проверку перед делением.

Еще одно потенциальное деление на ноль:

  • V609 Divide by zero. Denominator range [0..8]. ionbuilder.cpp 11844

Предупреждение PVS-Studio: V621 Consider inspecting the 'for' operator. It's possible that the loop will be executed incorrectly or won't be executed at all. nsmsgdbfolder.cpp 4501

NS_IMETHODIMP 
nsMsgDBFolder::GetDisplayRecipients(bool *displayRecipients)
{
  ....     
  // There's one FCC folder for sent mail, and one for sent news
  nsIMsgFolder *fccFolders[2];
  int numFccFolders = 0;
  for (int i = 0; i < numFccFolders; i++)
  {
    ....
  }
  ....
}

Анализатором было найдено подозрительное место, в котором цикл не проходит ни одной итерации. Причиной этого является переменная "numFccFolders", значение которой равно нулю. Возможно, это присваивание сделано с какой-то целью, но также возможно, что это опечатка. Комментарий и объявление указателя выше подсказывают, что переменная должна иметь значение 2.

Предупреждение PVS-Studio: V678 An object is used as an argument to its own method. Consider checking the first actual argument of the 'Assign' function. nsgenerichtmlelement.h 411

class nsGenericHTMLElement : public nsGenericHTMLElementBase,
                             public nsIDOMHTMLElement
{
  ....
  NS_IMETHOD GetItemId(nsAString& aId) final override {
    nsString id;
    GetItemId(id);
    aId.Assign(aId);
    return NS_OK;
  }
  ....
}

Само по себе использование объекта "aId" как аргумента в своем же методе не является ошибкой. Но этот код подозрителен тем, что в функции используется переменная с похожим названием "id". Это наводит на мысль, что здесь содержится опечатка и аргументом функции "aId.Assign" должна быть переменная "id".

Предупреждение PVS-Studio: V670 The uninitialized class member 'mWorkerConnection' is used to initialize the 'mWorkerStatements' member. Remember that members are initialized in the order of their declarations inside a class. domstoragedbthread.cpp 50

DOMStorageDBThread::DOMStorageDBThread()
: mWorkerStatements(mWorkerConnection)
, ....
{}

class DOMStorageDBThread final : public DOMStorageDBBridge
{
private:
  ....
  StatementCache mWorkerStatements; // <=line 304
  ....
  nsCOMPtr<mozIStorageConnection> mWorkerConnection; // <=line 309
  ....
}

При использовании списка инициализации следует помнить об одном нюансе: переменные инициализируется в том порядке, в каком они объявлены в классе, а порядок в списке инициализации значения не имеет. В этом коде переменная "mWorkerStatements" инициализируется объектом "mWorkerConnection" другого класса. Но на момент инициализации для этого объекта еще не был вызван конструктор, так как в классе он объявлен позже, чем переменная "mWorkerStatements". Чтобы исправить это, достаточно поменять местами объявление этих двух объектов в классе.

В этом классе прячется еще одна такая же ошибка:

  • V670 The uninitialized class member 'mReaderConnection' is used to initialize the 'mReaderStatements' member. Remember that members are initialized in the order of their declarations inside a class. domstoragedbthread.cpp 51

Заключение

Подводя итог хочу заметить, что PVS-Studio нашел много подозрительных мест в проекте Mozilla Thunderbird. Большинство из них относятся к сторонним библиотекам. Тем не менее и в самом Thunderbird нашлись интересные ошибки.

Написать большой проект без ошибок не под силу даже самым опытным и внимательным программистам. Для таких целей и существуют статические анализаторы кода. Их использование поможет вам сэкономить время на поиск старых ошибок и не допустить новых. Предлагаю попробовать PVS-Studio на вашем проекте: /ru/pvs-studio/download/.

Популярные статьи по теме
Как PVS-Studio оказался внимательнее, чем три с половиной программиста

Дата: 22 Окт 2018

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

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

Дата: 20 Мар 2017

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

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…
Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей

Дата: 21 Ноя 2018

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

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

Дата: 17 Янв 2019

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

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

Дата: 31 Май 2014

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

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

Дата: 22 Дек 2018

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

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

Дата: 14 Апр 2016

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

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

Дата: 30 Янв 2019

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

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

Дата: 31 Июл 2017

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

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

Дата: 27 Июн 2017

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

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

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

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

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