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

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

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

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

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

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

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


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

>
>
>
Проверка проекта Quake III Arena GPL

Проверка проекта Quake III Arena GPL

06 Фев 2012

Как известно, компания id Software выложила исходные коды многих своих игр. Мы уже проверяли некоторые из этих проектов. На этот раз мы решили проанализировать исходный код Quake III Arena GPL. Для анализа использовался статический анализатор PVS-Studio версии 4.54.

К сожалению, заметка о проверке получилась сухой и без развернутых комментариев. В Quake III Arena GPL мы не нашли ошибок о которых можно написать интересную статью. Вдобавок, некоторые из найденных ошибок мы уже встречали при проверке кода игры Doom 3.

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

  • Если ошибка встречается несколько раз, то описывается только один случай.
  • В статье не описаны несущественные ошибки.
  • Не приводятся фрагменты кода, где автор затрудняется быстро сделать вывод, имеется там ошибка или нет.

Читатель при желании может сам более внимательно изучить диагностические сообщения, выдаваемые PVS-Studio. Новая модель триала позволяет это легко сделать.

Фрагмент N1.

Диагностическое сообщение V511.

The sizeof() operator returns size of the pointer, and not of the array, in 'sizeof(src)' expression.

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );
}

Должно быть:

memcpy( mat, src, sizeof(float) * 3 * 3);

Фрагмент N2.

Диагностическое сообщение V501.

There are identical sub-expressions '(result->flags & 64)' to the left and to the right of the '||' operator.

void BotMoveToGoal(....)
{
  ...
  if ((result->flags & MOVERESULT_ONTOPOF_FUNCBOB) ||
      (result->flags & MOVERESULT_ONTOPOF_FUNCBOB))
  {
    ms->reachability_time = AAS_Time() + 5;
  }
  ...
}

Фрагмент N3.

Диагностическое сообщение V510.

The 'ScriptError' function is not expected to receive class-type variable as third actual argument.

typedef struct punctuation_s
{
  char *p;
  int n;
  struct punctuation_s *next;
} punctuation_t;

punctuation_t *punctuations;

int PS_ExpectTokenType(script_t *script, ....)
{
  ...
  ScriptError(script, "expected %s, found %s",
    script->punctuations[subtype], token->string);
  ...
}

Фрагмент N4.

Диагностическое сообщение V570.

The 'p->org[0]' variable is assigned to itself.

void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent)
{
  ...
  p->org[0] = p->org[0];
  p->org[1] = p->org[1];
  p->org[2] = p->org[2];
  ...
}

Фрагмент N5.

Диагностическое сообщение V568.

It's odd that the argument of sizeof() operator is the '& itemInfo' expression.

void CG_RegisterItemVisuals( int itemNum ) {
  itemInfo_t  *itemInfo;
  ...
  memset( itemInfo, 0, sizeof( &itemInfo ) );
}

Должно быть:

memset( itemInfo, 0, sizeof( *itemInfo ) );

Фрагмент N6.

Диагностическое сообщение V595.

The 'item' pointer was utilized before it was verified against nullptr. Check lines: 3865, 3869.

void Item_Paint(itemDef_t *item) {
  vec4_t red;
  menuDef_t *parent = (menuDef_t*)item->parent;
  red[0] = red[3] = 1;
  red[1] = red[2] = 0;

  if (item == NULL) {
    return;
  }
  ...
}

Фрагмент N7.

Диагностическое сообщение V557.

Array overrun is possible. The 'sizeof (bs->teamleader)' index is pointing beyond array bound.

typedef struct bot_activategoal_s
{
  ...
  float leadbackup_time;
  char teamleader[32];
  float askteamleader_time;
  ...
} bot_state_t;

void BotTeamAI(bot_state_t *bs) {
  ...
  bs->teamleader[sizeof(bs->teamleader)] = '\0';
  ...
}

Фрагмент N8.

Диагностическое сообщение V579.

The Com_Memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument.

void Cvar_Restart_f( void ) {
  cvar_t *var;
  ...
  // clear the var completely, since we
  // can't remove the index from the list
  Com_Memset( var, 0, sizeof( var ) );
  ...
}

Должно быть:

Com_Memset( var, 0, sizeof( *var ) );

Фрагмент N9.

Диагностическое сообщение V557.

Array overrun is possible. The '3' index is pointing beyond array bound.

void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors )
{
  int *pColors = ( int * ) dstColors;
  unsigned char invModulate[3];
  int c;
  ...
  invModulate[0]=255-backEnd.currentEntity->e.shaderRGBA[0];
  invModulate[1]=255-backEnd.currentEntity->e.shaderRGBA[1];
  invModulate[2]=255-backEnd.currentEntity->e.shaderRGBA[2];
  invModulate[3]=255-backEnd.currentEntity->e.shaderRGBA[3];
  ...  
}

Фрагмент N10.

Диагностическое сообщение V521.

Such expressions using the ',' operator are dangerous. Make sure the expression is correct.

void Q1_AllocMaxBSP(void)
{
  ...
  q1_allocatedbspmem +=
    Q1_MAX_MAP_CLIPNODES * sizeof(q1_dclipnode_t);
  ...
  q1_allocatedbspmem +=
    Q1_MAX_MAP_EDGES , sizeof(q1_dedge_t);
  ...
  q1_allocatedbspmem +=
    Q1_MAX_MAP_MARKSURFACES * sizeof(unsigned short);
  ...
}

Должно быть:

Q1_MAX_MAP_EDGES * sizeof(q1_dedge_t);

Фрагмент N11.

Диагностическое сообщение V595.

The 'node' pointer was utilized before it was verified against nullptr. Check lines: 769, 770.

void FloodPortals_r (node_t *node, int dist)
{
  ...
  if (node->occupied)
    Error("FloodPortals_r: node already occupied\n");
  if (!node)
  {
    Error("FloodPortals_r: NULL node\n");
  }
  ...
}

Фрагмент N12.

Диагностическое сообщение V501.

There are identical sub-expressions 'fabs(dir[1]) > test->radius' to the left and to the right of the '||' operator.

int VL_FindAdjacentSurface(....)
{
  ...
  if (fabs(dir[0]) > test->radius ||
      fabs(dir[1]) > test->radius ||
      fabs(dir[1]) > test->radius)
  {
  ...
}

Фрагмент N13.

Диагностическое сообщение V517.

The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 3333, 3335.

void CMainFrame::OnClipSelected() 
{
  ...
  if (g_bPatchBendMode)
    Patch_BendHandleENTER();
  else if (g_bPatchBendMode)
    Patch_InsDelHandleENTER();
  ...
}

Фрагмент N14.

Диагностическое сообщение V579.

The memset function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the third argument.

void CXYWnd::Paste()
{
  ...
  char* pBuffer = new char[nLen+1];
  memset( pBuffer, 0, sizeof(pBuffer) );
  ...
}

Должно быть:

memset( pBuffer, 0, (nLen+1) * sizeof(char) );

Фрагмент N15.

Диагностическое сообщение V519.

The 'numQuadCels' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1004, 1006.

static void setupQuad( long xOff, long yOff )
{
    ...
  numQuadCels  = (.....);
  numQuadCels += numQuadCels/4 + numQuadCels/16;
  numQuadCels += 64;
  numQuadCels  = (.....);
  numQuadCels += numQuadCels/4;
  numQuadCels += 64;
  ...
}

Фрагмент N16.

Диагностическое сообщение V537.

Consider reviewing the correctness of 'scale_x' item's usage.

void Terrain_AddMovePoint(....) {
  ...
  x = ( v[ 0 ] - p->origin[ 0 ] ) / p->scale_x;
  y = ( v[ 1 ] - p->origin[ 1 ] ) / p->scale_x;
  ...
}

Должно быть:

y = ( v[ 1 ] - p->origin[ 1 ] ) / p->scale_y;

Фрагмент N17.

Диагностическое сообщение V557.

Array overrun is possible. The value of 'i' index could reach 3.

int   numteamVotingClients[2];

void CalculateRanks( void ) {
  ...
  for ( i = 0; i < TEAM_NUM_TEAMS; i++ ) {
    level.numteamVotingClients[i] = 0;
  }
  ...
}

Фрагмент N18.

Диагностическое сообщение V591.

Non-void function should return a value.

static ID_INLINE int BigLong(int l)
{ LongSwap(l); }
Должно быть:
static ID_INLINE int BigLong(int l)
{ return LongSwap(l); }

Заключение

Чтобы найти все эти ошибки мне понадобилось около трех часов времени. В него включено время на скачивание исходных кодов, проверку, анализ результатов и выписывания понравившихся фрагментов кода. Как видите, статический анализатор является очень эффективным инструментом поиска ошибок. Впрочем, ещё более он эффективен при регулярном использовании.

Популярные статьи по теме
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

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

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

Дата: 17 Янв 2019

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

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

Дата: 31 Май 2014

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

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

Дата: 30 Янв 2019

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

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

Дата: 22 Окт 2018

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

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

Дата: 16 Окт 2017

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

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

Дата: 22 Дек 2018

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

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

Дата: 20 Мар 2017

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

В своей предыдущей статье я писал, что мне не нравится подход, при котором статические анализаторы кода оцениваются с помощью синтетических тестов. В статье приводился пример, воспринимаемый анализат…
Зло живёт в функциях сравнения

Дата: 19 Май 2017

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

Возможно, читатели помнят мою статью под названием "Эффект последней строки". В ней идёт речь о замеченной мной закономерности: ошибка чаще всего допускается в последней строке однотипных блоков текс…
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

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

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

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

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

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