PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Üks kõige kaasaegsemaid stsenaariume PVS-Studio analüsaatori kasutamiseks on selle integreerimine CI-süsteemidega. Ja kuigi peaaegu iga pideva integratsioonisüsteemi PVS-Studio projekti analüüsi saab sisse ehitada vaid mõne käsuga, muudame selle protsessi jätkuvalt veelgi mugavamaks. PVS-Studio toetab nüüd analüsaatori väljundi teisendamist TeamCity - TeamCity Inspections Type -vormingusse. Vaatame, kuidas see toimib.

Teave kasutatud tarkvara kohta

PVS-stuudio — C-, C++-, C#- ja Java-koodi staatiline analüsaator, mis on loodud eri tüüpi vigade leidmise ja parandamise hõlbustamiseks. Analüsaatorit saab kasutada operatsioonisüsteemides Windows, Linux ja macOS. Selles artiklis kasutame aktiivselt mitte ainult analüsaatorit ennast, vaid ka mõnda selle levitamise utiliiti.

CLmonitor — on jälgimisserver, mis jälgib kompilaatori käivitamist. See tuleb käivitada vahetult enne projekti ehitamise alustamist. Nuhkimisrežiimis peatab server kõigi toetatud kompilaatorite käigud. Väärib märkimist, et seda utiliiti saab kasutada ainult C/C++ projektide analüüsimiseks.

PlogConverter – utiliit analüsaatori aruannete teisendamiseks erinevatesse vormingutesse.

Info uuritava projekti kohta

Proovime seda funktsionaalsust praktilisel näitel – analüüsime OpenRCT2 projekti.

OpenRCT2 - mängu RollerCoaster Tycoon 2 (RCT2) avatud rakendus, laiendades seda uute funktsioonidega ja parandades vigu. Mängu käik keerleb lõbustuspargi ehitamise ja hooldamise ümber, mis sisaldab atraktsioone, poode ja rajatisi. Mängija peab püüdma teenida kasumit ja säilitada pargi head mainet, hoides samal ajal külalisi õnnelikuna. OpenRCT2 võimaldab mängida nii stsenaariumis kui ka liivakastis. Stsenaariumid nõuavad mängijalt konkreetse ülesande täitmist määratud aja jooksul, samas kui Sandbox võimaldab mängijal ehitada paindlikuma pargi ilma piirangute ja rahaliste vahenditeta.

reguleerimine

Aja säästmiseks jätan tõenäoliselt installimise vahele ja alustan hetkest, mil minu arvutis töötab TeamCity server. Peame minema aadressile localhost:{installiprotsessi käigus määratud port} (minu puhul localhost:9090) ja sisestama autoriseerimisandmed. Pärast sisenemist tervitavad meid:

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Klõpsake nuppu Loo projekt. Järgmisena valige Käsitsi ja täitke väljad.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Pärast nupu vajutamist Looma, tervitab meid seadetega aken.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Klõpsame Loo ehituse konfiguratsioon.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Täitke väljad ja klõpsake nuppu Looma. Näeme akent, mis palub teil valida versioonihaldussüsteem. Kuna allikad asuvad juba kohapeal, klõpsake nuppu Jäta vahele.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Lõpuks liigume edasi projekti sätete juurde.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Lisame kokkupaneku etapid, selleks klõpsake: Järje etapid -> Lisa ehitusetapp.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Siin valime:

  • Jooksja tüüp -> käsurida
  • Käivita -> Kohandatud skript

Kuna analüüsi teostame projekti koostamise ajal, peaks kokkupanek ja analüüs olema üks samm, seega täitke väli Kohandatud skript:

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Üksikuid samme vaatame hiljem. Oluline on, et analüsaatori laadimine, projekti kokkupanemine, analüüsimine, aruande väljastamine ja vormindamine võtavad vaid üksteist koodirida.

Viimase asjana peame määrama keskkonnamuutujad, mille loetavuse parandamiseks olen välja toonud mõned viisid. Selleks liigume edasi: Parameetrid -> Lisa uus parameeter ja lisage kolm muutujat:

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Kõik, mida pead tegema, on vajutada nuppu jooks paremas ülanurgas. Projekti kokkupanemise ja analüüsimise ajal räägin teile stsenaariumist.

Otse skript

Esiteks peame alla laadima uusima PVS-Studio distributsiooni. Selleks kasutame Chocolatey paketihaldurit. Neile, kes soovivad selle kohta rohkem teada saada, on vastav artikkel:

choco install pvs-studio -y

Järgmisena käivitame projekti CLMonitor ehituse jälgimise utiliidi.

%CLmon% monitor –-attach

Seejärel koostame projekti keskkonnamuutujana MSB on tee MSBuildi versioonini, mida ma pean ehitama

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

Sisestame PVS-Studio sisselogimis- ja litsentsivõtme:

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

Kui ehitamine on lõppenud, käivitage eeltöödeldud failide ja staatilise analüüsi loomiseks uuesti CLMonitor:

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

Seejärel kasutame teist distributsiooni utiliiti. PlogConverter teisendab aruande standardvormingust TeamCity-spetsiifiliseks vorminguks. Tänu sellele saame seda vaadata otse ehitusaknas.

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

Viimane samm on vormindatud aruande kuvamine stdout, kust TeamCity parser selle üles võtab.

type "C:tempptest.plog_TeamCity.txt"

Täielik skripti kood:

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"

Vahepeal on projekti kokkupanek ja analüüs edukalt lõpetatud, saame vahekaardile minna Projektid ja veendu selles.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Nüüd klõpsame edasi Ülevaatused Kokkuanalüsaatori aruande vaatamiseks:

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Hoiatused on rühmitatud diagnostikareeglite numbrite järgi. Koodis navigeerimiseks peate klõpsama hoiatusega rea ​​numbril. Klõpsates paremas ülanurgas oleval küsimärgil, avaneb uus dokumentatsiooniga vahekaart. Samuti saate koodis navigeerida, klõpsates analüsaatori hoiatusega rea ​​numbril. Kasutamisel on võimalik navigeerida kaugarvutist SourceTreeRoot marker. Kõik, kes on huvitatud sellest analüsaatori töörežiimist, saavad tutvuda vastava jaotisega dokumentatsioon.

Analüsaatori tulemuste vaatamine

Nüüd, kui oleme järgu juurutamise ja konfigureerimise lõpetanud, vaatame mõningaid huvitavaid hoiatusi, mis leiti vaadeldavast projektist.

Hoiatus N1

V773 [CWE-401] Erand tehti ilma 'tulemuse' kursorit vabastamata. Võimalik on mäluleke. libopenct2 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;
}

Analüsaator märkas viga, mis tekkis pärast mälu dünaamilist eraldamist Loo objekt, kui erand ilmneb, mälu ei tühjendata ja tekib mäluleke.

Hoiatus N2

V501 Kaubast '|' vasakul ja paremal on identsed alamväljendid '(1ULL << WIDX_MONTH_BOX)' operaator. libopenct2ui 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),
  ....
};

Vähesed inimesed peale staatilise analüsaatori suudavad selle tähelepanelikkuse testi läbida. See copy-paste näide on just sel põhjusel hea.

Hoiatused N3

V703 On veider, et tuletatud klassi 'RCT12BannerElement' väli 'lipud' kirjutab üle põhiklassi 'RCT12TileElementBase' välja. Kontrollread: RCT12.h:570, RCT12.h:259. libopenct2 RCT12.h 570

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

Muidugi ei ole sama nimega muutuja kasutamine põhiklassis ja järeltulijas alati viga. Pärimistehnoloogia ise aga eeldab, et alamklassis on olemas kõik vanemklassi väljad. Deklareerides pärijas samanimelised väljad, tekitame segaduse.

Hoiatus N4

V793 On kummaline, et lause „imageDirection / 8” tulemus on tingimuse osa. Võib-olla oleks tulnud seda väidet millegi muuga võrrelda. libopenct2 ObservationTower.cpp 38

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

Vaatame lähemalt. Väljendus imageDirection/8 on vale, kui imageDirection on vahemikus -7 kuni 7. Teine osa: (imageDirection / 8) != 3 kontrollid imageDirection väljaspool vahemikku jäämise eest: vastavalt -31 kuni -24 ja 24 kuni 31. Mulle tundub üsna kummaline kontrollida sel viisil numbreid teatud vahemikku ja isegi kui selles koodiosas pole viga, soovitaksin need tingimused selgemaks muuta. See teeks nende inimeste elu palju lihtsamaks, kes seda koodi loevad ja hooldavad.

Hoiatus N5

V587 Seda tüüpi ülesannete paaritu jada: A = B; B = A;. Kontrollread: 1115, 1118. libopenct2ui 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;
      ....
  }
  ....
}

See koodifragment saadi suure tõenäosusega dekompileerimise teel. Seejärel eemaldati jäetud kommentaari järgi otsustades osa mittetöötavast koodist. Paar operatsiooni on aga veel jäänud kursori ID, millel pole samuti erilist mõtet.

Hoiatus N6

V1004 [CWE-476] Mängija osutit kasutati ebaturvaliselt pärast seda, kui see kontrolliti nullptr-i vastu. Kontrollread: 2085, 2094. libopenct2 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);                    // <=
  }
  ....
}

Seda koodi on üsna lihtne parandada; peate seda lihtsalt kolmandat korda kontrollima mängija nullkursorile või lisage see tingimuslause kehasse. Mina pakuks teist varianti:

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);
    }
  }
  ....
}

Hoiatus N7

V547 [CWE-570] Avaldis 'nimi == nullptr' on alati väär. libopenct2 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));
    ....
  }
  ....
}

Saate ühe hoobiga lahti saada raskesti loetavast koodireast ja lahendada probleemi nullptr. Soovitan koodi muuta järgmiselt:

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);
    ....
  }
  ....
}

Hoiatus N8

V1048 [CWE-1164] Muutujale 'ColumnHeaderPressedCurrentState' määrati sama väärtus. libopenct2ui CustomListView.cpp 510

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

Kood näeb üsna kummaline välja. Mulle tundub, et kas tingimuses või muutuja ümber määramisel oli kirjaviga ColumnHeaderPressedCurrentState tähendused vale.

Väljund

Nagu näeme, on PVS-Studio staatilise analüsaatori integreerimine oma TeamCity projekti üsna lihtne. Selleks piisab vaid ühe väikese konfiguratsioonifaili kirjutamisest. Koodi kontrollimine võimaldab tuvastada probleemid kohe pärast kokkupanekut, mis aitab need kõrvaldada, kui muudatuste keerukus ja maksumus on endiselt madal.

PVS-Studio ja pidev integreerimine: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs
Kui soovite seda artiklit inglise keelt kõneleva publikuga jagada, kasutage tõlkelinki: Vladislav Stolyarov. PVS-Studio ja pidev integratsioon: TeamCity. Open RollerCoaster Tycoon 2 projekti analüüs.

Allikas: www.habr.com

Lisa kommentaar