PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Яке аз сенарияҳои муосири истифодаи анализатори PVS-Studio ин ҳамгироии он бо системаҳои CI мебошад. Ва гарчанде ки таҳлили лоиҳаи PVS-Studio аз қариб ҳама гуна системаи муттаҳидсозии муттасил метавонад дар як чанд фармон сохта шавад, мо минбаъд низ ин равандро қулайтар мегардонем. PVS-Studio ҳоло барои табдил додани баромади анализатор ба формати TeamCity - Type Inspections TeamCity дастгирӣ мекунад. Биёед бубинем, ки он чӣ гуна кор мекунад.

Маълумот дар бораи нармафзори истифодашуда

PVS-Студияи — таҳлилгари статикии C, C++, C# ва Java, ки барои осон кардани вазифаи дарёфт ва ислоҳи хатогиҳои гуногун пешбинӣ шудааст. Анализаторро дар Windows, Linux ва macOS истифода бурдан мумкин аст. Дар ин мақола мо на танҳо худи анализатор, балки баъзе утилитҳоро аз тақсимоти он фаъолона истифода хоҳем кард.

CLMMonitor — сервери мониторингест, ки оғозёбии компиляторҳоро назорат мекунад. Он бояд фавран пеш аз оғози сохтани лоиҳаи шумо иҷро карда шавад. Дар ҳолати ҷустуҷӯ, сервер иҷрои ҳама компиляторҳои дастгирӣшавандаро бозмедорад. Бояд қайд кард, ки ин утилита метавонад танҳо барои таҳлили лоиҳаҳои C/C++ истифода шавад.

Табдилдиҳандаи Plog - утилита барои табдил додани гузоришҳои таҳлилгар ба форматҳои гуногун.

Маълумот дар бораи лоиҳаи мавриди омӯзиш

Биёед ин функсияро дар мисоли амалӣ санҷем - биёед лоиҳаи OpenRCT2-ро таҳлил кунем.

OpenRCT2 - татбиқи кушоди бозии RollerCoaster Tycoon 2 (RCT2), васеъ кардани он бо функсияҳои нав ва ислоҳи хатогиҳо. Бозӣ дар атрофи сохтан ва нигоҳдории боғи тафреҳӣ, ки дорои аттракционҳо, мағозаҳо ва иншоот аст, мегузарад. Бозингар бояд кӯшиш кунад, ки фоида ба даст орад ва обрӯи хуби паркро нигоҳ дошта, меҳмононро хушбахт нигоҳ дорад. OpenRCT2 ба шумо имкон медиҳад, ки ҳам дар сенария ва ҳам дар қуттии қум бозӣ кунед. Сенарияҳо аз плеер талаб мекунанд, ки вазифаи мушаххасро дар муддати муқарраршуда анҷом диҳад, дар ҳоле ки Sandbox ба плеер имкон медиҳад, ки бидуни маҳдудият ё маблағ як боғи фасеҳтар созад.

танзим

Барои сарфаи вақт, ман эҳтимол раванди насбкуниро гузаред ва аз лаҳзае, ки сервери TeamCity дар компютери ман кор мекунад, оғоз мекунам. Мо бояд ба: localhost:{порте, ки дар ҷараёни насб нишон дода шудааст} (дар ҳолати ман, localhost:9090) равем ва маълумоти авторизатсияро ворид кунем. Пас аз ворид шудан моро инҳо пешвоз мегиранд:

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Тугмаи Эҷоди лоиҳаро клик кунед. Баъдан, ба таври дастӣ -ро интихоб кунед ва майдонҳоро пур кунед.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Пас аз пахш кардани тугма сохтан, моро равзанаи танзимот пешвоз мегиранд.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Биёед клик кунем Эҷоди конфигуратсияи сохтмон.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Майдонҳоро пур кунед ва клик кунед сохтан. Мо тирезаеро мебинем, ки аз шумо хоҳиш мекунад, ки системаи идоракунии версияро интихоб кунед. Азбаски манбаъҳо аллакай дар маҳаллӣ ҷойгиранд, клик кунед гузарондан.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Дар ниҳоят, мо ба танзимоти лоиҳа мегузарем.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Биёед қадамҳои васлкуниро илова кунем, то ин клик кунед: Қадамҳои сохтани -> Қадами сохтмон илова кунед.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Дар ин ҷо мо интихоб мекунем:

  • Навъи даванда -> Сатри Фармон
  • Иҷро кунед -> Скрипти фармоишӣ

Азбаски мо ҳангоми таҳияи лоиҳа таҳлил хоҳем кард, ҷамъоварӣ ва таҳлил бояд як қадам бошад, бинобар ин майдонро пур кунед Навишти оддӣ:

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Мо қадамҳои алоҳидаро баъдтар дида мебароем. Муҳим аст, ки барои бор кардани анализатор, монтаж кардани лоиҳа, таҳлили он, баровардани ҳисобот ва формат кардани он ҳамагӣ ёздаҳ сатри код лозим аст.

Охирин чизе, ки мо бояд анҷом диҳем, ин муқаррар кардани тағирёбандаҳои муҳити зист аст, ки ман баъзе роҳҳои беҳтар кардани хондани онҳоро тавсиф кардам. Барои ин, биёед идома диҳем: Параметрҳо -> Илова кардани параметри нав ва се тағирёбанда илова кунед:

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Шумо танҳо бояд тугмаро пахш кунед давидан дар кунҷи рости боло. Ҳангоми ҷамъоварӣ ва таҳлили лоиҳа, ман ба шумо дар бораи скрипт нақл мекунам.

Скрипти мустақим

Аввалан, мо бояд паҳнкунии охирини PVS-Studio-ро зеркашӣ кунем. Барои ин мо мудири бастаи Chocolatey -ро истифода мебарем. Барои онҳое, ки мехоҳанд дар ин бора маълумоти бештар гиранд, мувофиқ вуҷуд дорад мақола:

choco install pvs-studio -y

Минбаъд, биёед барномаи пайгирии пайгирии лоиҳаи CLMonitor -ро оғоз кунем.

%CLmon% monitor –-attach

Сипас, мо лоиҳаро ҳамчун тағирёбандаи муҳити зист месозем MSB роҳи версияи MSBuild аст, ки ман бояд бунёд кунам

%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable

Биёед воридшавӣ ва калиди иҷозатномаро барои PVS-Studio ворид кунем:

%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%

Пас аз ба итмом расидани сохтмон, CLMonitor-ро дубора иҷро кунед, то файлҳои коркардшуда ва таҳлили статикиро тавлид кунед:

%CLmon% analyze -l "c:ptest.plog"

Он гоҳ мо як утилитаи дигарро аз тақсимоти худ истифода хоҳем кард. PlogConverter гузоришро аз формати стандартӣ ба формати махсуси TeamCity табдил медиҳад. Ба шарофати ин, мо метавонем онро мустақиман дар равзанаи сохтмон бубинем.

%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"

Қадами охирин ин намоиш додани гузориши форматшуда дар истодагарӣ, ки он аз ҷониби таҳлилгари TeamCity гирифта мешавад.

type "C:tempptest.plog_TeamCity.txt"

Рамзи пурраи скрипт:

choco install pvs-studio -y
%CLmon% monitor --attach
set platform=x64
%MSB% %ProjPath% /t:clean
%MSB% %ProjPath% /t:rebuild /p:configuration=release
%MSB% %ProjPath% /t:g2
%MSB% %ProjPath% /t:PublishPortable
%PVS-Studio_cmd% credentials --username %PVS_Name% --serialNumber %PVS_Key%
%CLmon% analyze -l "c:ptest.plog"
%PlogConverter% "c:ptest.plog" --renderTypes=TeamCity -o "C:temp"
type "C:tempptest.plog_TeamCity.txt"

Дар айни замон, монтаж ва таҳлили лоиҳа бомуваффақият анҷом ёфт, мо метавонем ба ҷадвал равем Лоиҳаҳо ва боварӣ ҳосил кунед.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Акнун биёед клик кунем Ҳамагӣ санҷишҳоБарои дидани гузориши анализатор:

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Огоҳӣ аз рӯи рақамҳои қоидаҳои ташхис гурӯҳбандӣ карда мешаванд. Барои гузаштан аз код, шумо бояд рақами сатри огоҳиро пахш кунед. Ангуштзании аломати савол дар кунҷи рости боло ба шумо ҷадвали нав бо ҳуҷҷатҳоро мекушояд. Шумо инчунин метавонед тавассути клик кардани рақами сатр бо огоҳии анализатор тавассути код паймоиш кунед. Ҳангоми истифода аз компютери дурдаст паймоиш кардан мумкин аст SourceTreeRoot маркер. Ҳар касе, ки ба ин режими кори анализатор таваҷҷӯҳ дорад, метавонад бо бахши дахлдор шинос шавад хуччатхо.

Намоиши натиҷаҳои анализатор

Акнун, ки мо ҷойгиркунӣ ва танзими сохтмонро анҷом додем, биёед ба баъзе огоҳиҳои ҷолибе, ки дар лоиҳае, ки мо мавриди назар қарор доранд, дида бароем.

Огоҳӣ N1

V773 [CWE-401] Истисно бидуни интишори нишондиҳандаи "натиҷа" партофта шуд. Ихроҷи хотира имконпазир аст. libopenrct2 ObjectFactory.cpp 443

Object* CreateObjectFromJson(....)
{
  Object* result = nullptr;
  ....
  result = CreateObject(entry);
  ....
  if (readContext.WasError())
  {
    throw std::runtime_error("Object has errors");
  }
  ....
}

Object* CreateObject(const rct_object_entry& entry)
{
  Object* result;
  switch (entry.GetType())
  {
    case OBJECT_TYPE_RIDE:
      result = new RideObject(entry);
      break;
    case OBJECT_TYPE_SMALL_SCENERY:
      result = new SmallSceneryObject(entry);
      break;
    case OBJECT_TYPE_LARGE_SCENERY:
      result = new LargeSceneryObject(entry);
      break;
    ....
    default:
      throw std::runtime_error("Invalid object type");
  }
  return result;
}

Анализатор хатоеро пай бурд, ки пас аз ба таври динамикӣ тақсим кардани хотира дар Эҷоди Объект, вақте ки истисно рух медиҳад, хотира тоза карда намешавад ва ихроҷи хотира рух медиҳад.

Огоҳӣ N2

V501 Зер ифодаҳои якхела '(1ULL << WIDX_MONTH_BOX)' дар тарафи чап ва рости '|' мавҷуданд. оператор. libopenrct2ui Cheats.cpp 487

static uint64_t window_cheats_page_enabled_widgets[] = 
{
  MAIN_CHEAT_ENABLED_WIDGETS |
  (1ULL << WIDX_NO_MONEY) |
  (1ULL << WIDX_ADD_SET_MONEY_GROUP) |
  (1ULL << WIDX_MONEY_SPINNER) |
  (1ULL << WIDX_MONEY_SPINNER_INCREMENT) |
  (1ULL << WIDX_MONEY_SPINNER_DECREMENT) |
  (1ULL << WIDX_ADD_MONEY) |
  (1ULL << WIDX_SET_MONEY) |
  (1ULL << WIDX_CLEAR_LOAN) |
  (1ULL << WIDX_DATE_SET) |
  (1ULL << WIDX_MONTH_BOX) |  // <=
  (1ULL << WIDX_MONTH_UP) |
  (1ULL << WIDX_MONTH_DOWN) |
  (1ULL << WIDX_YEAR_BOX) |
  (1ULL << WIDX_YEAR_UP) |
  (1ULL << WIDX_YEAR_DOWN) |
  (1ULL << WIDX_DAY_BOX) |
  (1ULL << WIDX_DAY_UP) |
  (1ULL << WIDX_DAY_DOWN) |
  (1ULL << WIDX_MONTH_BOX) |  // <=
  (1ULL << WIDX_DATE_GROUP) |
  (1ULL << WIDX_DATE_RESET),
  ....
};

Теъдоди ками одамон ғайр аз анализатори статикӣ метавонанд аз ин санҷиши диққат гузаранд. Ин мисоли нусхабардорӣ ва часбонед, маҳз барои ҳамин хуб аст.

Огоҳӣ N3

V703 Аҷиб аст, ки майдони 'парчамҳо' дар синфи ҳосилшудаи 'RCT12BannerElement' майдонро дар синфи асосии 'RCT12TileElementBase' аз нав менависад. Хатҳои тафтиш: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

struct RCT12SpriteBase
{
  ....
  uint8_t flags;
  ....
};
struct rct1_peep : RCT12SpriteBase
{
  ....
  uint8_t flags;
  ....
};

Албатта, истифодаи тағирёбанда бо як ном дар синфи асосӣ ва насл на ҳамеша хато аст. Бо вуҷуди ин, худи технологияи меросӣ тахмин мекунад, ки тамоми соҳаҳои синфи волидайн дар синфи кӯдак мавҷуданд. Бо эълон кардани майдонҳо бо ҳамон ном дар ворисон, мо нофаҳмиҳо эҷод мекунем.

Огоҳӣ N4

V793 Аҷиб аст, ки натиҷаи изҳороти 'imageDirection / 8' як қисми шарт аст. Шояд ин изҳоротро бо чизи дигар муқоиса кардан лозим буд. libopenrct2 ObservationTower.cpp 38

void vehicle_visual_observation_tower(...., int32_t imageDirection, ....)
{
  if ((imageDirection / 8) && (imageDirection / 8) != 3)
  {
    ....
  }
  ....
}

Биёед муфассалтар дида бароем. Ифода imageDirection/8 дурӯғ мешавад, агар Самти тасвир дар доираи аз -7 то 7 аст. Қисми дуюм: (imageDirection / 8) != 3 чекҳо Самти тасвир барои берун аз диапазон будан: мутаносибан аз -31 то -24 ва аз 24 то 31. Бо ин роҳ тафтиш кардани рақамҳо барои ворид шудан ба диапазони муайян барои ман хеле аҷиб менамояд ва ҳатто агар дар ин порчаи код ягон хатогӣ вуҷуд надошта бошад ҳам, ман тавсия медиҳам, ки ин шартҳоро аз нав нависам, то равшантар бошад. Ин барои одамоне, ки ин кодро мехонанд ва нигоҳ медоштанд, ҳаётро хеле осонтар мегардонад.

Огоҳӣ N5

V587 пайдарпайии тоқи супоришҳои ин гуна: A = B; B = A;. Хатҳои тафтиш: 1115, 1118. libopenrct2ui MouseInput.cpp 1118

void process_mouse_over(....)
{
  ....
  switch (window->widgets[widgetId].type)
  {
    case WWT_VIEWPORT:
      ebx = 0;
      edi = cursorId;                                 // <=
      // Window event WE_UNKNOWN_0E was called here,
      // but no windows actually implemented a handler and
      // it's not known what it was for
      cursorId = edi;                                 // <=
      if ((ebx & 0xFF) != 0)
      {
        set_cursor(cursorId);
        return;
      }
      break;
      ....
  }
  ....
}

Ин порчаи код эҳтимолан тавассути декомпиляция ба даст оварда шудааст. Сипас, аз рӯи шарҳи гузошташуда, як қисми коди корношоям хориҷ карда шуд. Бо вуҷуди ин, ҳанӯз як ду амалиёт боқӣ мондааст курсор ID, ки он низ чандон маъно надорад.

Огоҳӣ N6

V1004 [CWE-476] Нишондиҳандаи 'плеер' пас аз тасдиқи он бар зидди nullptr, ба таври бехатар истифода шуд. Хатҳои тафтиш: 2085, 2094. libopenrct2 Network.cpp 2094

void Network::ProcessPlayerList()
{
  ....
  auto* player = GetPlayerByID(pendingPlayer.Id);
  if (player == nullptr)
  {
    // Add new player.
    player = AddPlayer("", "");
    if (player)                                          // <=
    {
      *player = pendingPlayer;
       if (player->Flags & NETWORK_PLAYER_FLAG_ISSERVER)
       {
         _serverConnection->Player = player;
       }
    }
    newPlayers.push_back(player->Id);                    // <=
  }
  ....
}

Ин кодро ислоҳ кардан хеле осон аст; шумо бояд онро бори сеюм тафтиш кунед бозингар ба нишондиҳандаи нул, ё онро ба ҷузъи изҳороти шартӣ илова кунед. Ман варианти дуюмро пешниҳод мекунам:

void Network::ProcessPlayerList()
{
  ....
  auto* player = GetPlayerByID(pendingPlayer.Id);
  if (player == nullptr)
  {
    // Add new player.
    player = AddPlayer("", "");
    if (player)
    {
      *player = pendingPlayer;
      if (player->Flags & NETWORK_PLAYER_FLAG_ISSERVER)
      {
        _serverConnection->Player = player;
      }
      newPlayers.push_back(player->Id);
    }
  }
  ....
}

Огоҳӣ N7

V547 [CWE-570] Ифодаи 'ном == nullptr' ҳамеша нодуруст аст. libopenrct2 ServerList.cpp 102

std::optional<ServerListEntry> ServerListEntry::FromJson(...)
{
  auto name = json_object_get(server, "name");
  .....
  if (name == nullptr || version == nullptr)
  {
    ....
  }
  else
  {
    ....
    entry.name = (name == nullptr ? "" : json_string_value(name));
    ....
  }
  ....
}

Шумо метавонед бо як зарба аз хати коди хондан душвор халос шавед ва мушкилотро бо тафтиши он ҳал кунед. nullptr. Ман тавсия медиҳам, ки кодро ба таври зерин тағир диҳед:

std::optional<ServerListEntry> ServerListEntry::FromJson(...)
{
  auto name = json_object_get(server, "name");
  .....
  if (name == nullptr || version == nullptr)
  {
    name = ""
    ....
  }
  else
  {
    ....
    entry.name = json_string_value(name);
    ....
  }
  ....
}

Огоҳӣ N8

V1048 [CWE-1164] Тағйирёбандаи 'ColumnHeaderPressedCurrentState' ҳамон арзиш таъин карда шуд. libopenrct2ui CustomListView.cpp 510

void CustomListView::MouseUp(....)
{
  ....
  if (!ColumnHeaderPressedCurrentState)
  {
    ColumnHeaderPressed = std::nullopt;
    ColumnHeaderPressedCurrentState = false;
    Invalidate();
  }
}

Рамз хеле аҷиб менамояд. Ба назарам, дар шарт ва ё ҳангоми аз нав таъин кардани тағирёбанда хатои хаттӣ вуҷуд дошт ColumnHeaderPressedCurrentState арзишҳо бардурӯғ.

хулоса

Тавре ки мо мебинем, ҳамгироӣ кардани таҳлилгари статикии PVS-Studio ба лоиҳаи TeamCity-и худ хеле содда аст. Барои ин навиштан танҳо як файли конфигуратсияи хурд кофӣ аст. Санҷиши код ба шумо имкон медиҳад, ки мушкилотро фавран пас аз васлкунӣ муайян кунед, ки ҳангоми кам будани мураккабӣ ва арзиши тағирот ба бартараф кардани онҳо кӯмак мекунад.

PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2
Агар шумо хоҳед, ки ин мақоларо бо шунавандагони англисзабон мубодила кунед, лутфан истиноди тарҷумаро истифода баред: Владислав Столяров. PVS-Studio ва ҳамгироии доимӣ: TeamCity. Таҳлили лоиҳаи Open RollerCoaster Tycoon 2.

Манбаъ: will.com

Илова Эзоҳ