PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Een van die mees huidige scenario's vir die gebruik van die PVS-Studio-ontleder is die integrasie daarvan met CI-stelsels. En alhoewel die ontleding van 'n PVS-Studio-projek vanaf byna enige deurlopende integrasiestelsel in net 'n paar opdragte ingebou kan word, gaan ons voort om hierdie proses nog geriefliker te maak. PVS-Studio het nou ondersteuning vir die omskakeling van ontleder-uitset in 'n formaat vir TeamCity - TeamCity Inspections Type. Kom ons kyk hoe dit werk.

Inligting oor die sagteware wat gebruik word

PVS-ateljee — 'n statiese ontleder van C, C++, C# en Java-kode, ontwerp om die taak om verskillende tipes foute te vind en reg te stel, te vergemaklik. Die ontleder kan op Windows, Linux en macOS gebruik word. In hierdie artikel sal ons nie net die ontleder self aktief gebruik nie, maar ook sommige nutsprogramme uit die verspreiding daarvan.

CLMonitor - is 'n moniteringsbediener wat samesteller bekendstellings monitor. Dit moet onmiddellik uitgevoer word voordat u begin om u projek te bou. In snuffelmodus sal die bediener lopies van alle ondersteunde samestellers onderskep. Dit is opmerklik dat hierdie hulpprogram slegs gebruik kan word om C/C++-projekte te ontleed.

PlogConverter – 'n program om ontlederverslae in verskillende formate om te skakel.

Inligting oor die projek wat bestudeer word

Kom ons probeer hierdie funksionaliteit op 'n praktiese voorbeeld - kom ons ontleed die OpenRCT2-projek.

OopRCT2 - 'n oop implementering van die speletjie RollerCoaster Tycoon 2 (RCT2), wat dit uitbrei met nuwe funksies en foute regmaak. Speletjie draai om die bou en instandhouding van 'n pretpark wat ritte, winkels en fasiliteite bevat. Die speler moet probeer om wins te maak en die park se goeie reputasie te behou terwyl gaste gelukkig hou. OpenRCT2 laat jou toe om in beide scenario en sandbox te speel. Scenario's vereis dat die speler 'n spesifieke taak binne 'n vasgestelde tyd voltooi, terwyl Sandbox die speler toelaat om 'n meer buigsame park te bou sonder enige beperkings of finansies.

aanpassing

Om tyd te bespaar, sal ek waarskynlik die installasieproses oorslaan en begin vanaf die oomblik dat ek die TeamCity-bediener op my rekenaar het. Ons moet gaan na: localhost:{poort gespesifiseer tydens die installasieproses} (in my geval, localhost:9090) en magtigingsdata invoer. Nadat ons ingegaan het sal ons begroet word deur:

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Klik op die Skep projek-knoppie. Kies dan Handmatig en vul die velde in.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Nadat u die knoppie gedruk het Skep, word ons begroet deur 'n venster met instellings.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Kom ons klik Skep bou-konfigurasie.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Vul die velde in en klik Skep. Ons sien 'n venster wat jou vra om 'n weergawebeheerstelsel te kies. Aangesien die bronne reeds plaaslik geleë is, klik Slaan oor.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Ten slotte gaan ons aan na die projekinstellings.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Kom ons voeg monteerstappe by, om dit te doen, klik: Boustappe -> Voeg boustap by.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Hier kies ons:

  • Runner tipe -> Command Line
  • Hardloop -> Pasgemaakte skrip

Aangesien ons analise tydens projeksamestelling sal uitvoer, moet samestelling en ontleding een stap wees, so vul die veld in Aangepaste skrif:

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Ons sal later na individuele stappe kyk. Dit is belangrik dat die laai van die ontleder, die samestelling van die projek, die ontleding daarvan, die uitvoer van die verslag en die formatering daarvan slegs elf reëls kode neem.

Die laaste ding wat ons moet doen is om die omgewingsveranderlikes in te stel, wat ek 'n paar maniere uiteengesit het om hul leesbaarheid te verbeter. Om dit te doen, kom ons gaan aan: Parameters -> Voeg nuwe parameter by en voeg drie veranderlikes by:

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Al wat jy hoef te doen is om die knoppie te druk Run in die regter boonste hoek. Terwyl die projek saamgestel en ontleed word, sal ek jou van die draaiboek vertel.

Skryf direk

Eerstens moet ons die nuutste PVS-Studio-verspreiding aflaai. Hiervoor gebruik ons ​​die Chocolatey-pakketbestuurder. Vir diegene wat meer hieroor wil weet, is daar 'n ooreenstemmende статья:

choco install pvs-studio -y

Kom ons begin dan die CLMonitor-projekbou-opsporingshulpmiddel.

%CLmon% monitor –-attach

Dan sal ons die projek as 'n omgewingsveranderlike bou MSB is die pad na die weergawe van MSBuild wat ek moet bou

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

Kom ons voer die aanmeld- en lisensiesleutel vir PVS-Studio in:

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

Nadat die bou voltooi is, voer CLMonitor weer uit om voorafverwerkte lêers en statiese analise te genereer:

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

Dan sal ons 'n ander hulpprogram uit ons verspreiding gebruik. PlogConverter skakel 'n verslag van 'n standaardformaat na 'n TeamCity-spesifieke formaat om. Danksy dit sal ons dit direk in die bouvenster kan sien.

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

Die laaste stap is om die geformateerde verslag in te vertoon standout, waar dit deur die TeamCity-ontleder opgetel sal word.

type "C:tempptest.plog_TeamCity.txt"

Volledige skrif kode:

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"

Intussen is die samestelling en ontleding van die projek suksesvol afgehandel, ons kan na die blad gaan projekte en maak seker daarvan.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Kom ons klik nou op Inspeksies Totaalom na die ontlederverslag te gaan kyk:

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
Waarskuwings word volgens diagnostiese reëlnommers gegroepeer. Om deur die kode te navigeer, moet jy op die reëlnommer met die waarskuwing klik. As u op die vraagteken in die regter boonste hoek klik, sal u 'n nuwe oortjie met dokumentasie oopmaak. Jy kan ook deur die kode navigeer deur op die reëlnommer met die ontlederwaarskuwing te klik. Navigasie vanaf 'n afgeleë rekenaar is moontlik wanneer dit gebruik word SourceTreeRoot merker. Enigiemand wat belangstel in hierdie werkswyse van die ontleder kan hulself vergewis van die ooreenstemmende afdeling dokumentasie.

Kyk na die ontleder se resultate

Noudat ons klaar is met die implementering en konfigurasie van die bou, kom ons kyk na 'n paar interessante waarskuwings wat gevind word in die projek waarna ons kyk.

Waarskuwing N1

V773 [CWE-401] Die uitsondering is gegooi sonder om die 'resultaat'-wyser vry te laat. 'n Geheuelek is moontlik. 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;
}

Die ontleder het 'n fout opgemerk wat na die dinamiese toewysing van geheue in Skep Voorwerp, wanneer 'n uitsondering voorkom, word die geheue nie uitgevee nie, en 'n geheuelek vind plaas.

Waarskuwing N2

V501 Daar is identiese sub-uitdrukkings '(1ULL << WIDX_MONTH_BOX)' links en regs van die '|' operateur. 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),
  ....
};

Min mense anders as 'n statiese ontleder kan hierdie aandagstoets slaag. Hierdie copy-paste-voorbeeld is juis om hierdie rede goed.

Waarskuwings N3

V703 Dit is vreemd dat die 'vlag'-veld in die afgeleide klas 'RCT12BannerElement' veld in die basisklas 'RCT12TileElementBase' oorskryf. Kontroleer lyne: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

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

Die gebruik van 'n veranderlike met dieselfde naam in die basisklas en in die afstammeling is natuurlik nie altyd 'n fout nie. Oorerwingstegnologie self aanvaar egter dat al die velde van die ouerklas in die kinderklas teenwoordig is. Deur velde met dieselfde naam in die erfgenaam te verklaar, lei ons verwarring.

Waarskuwing N4

V793 Dit is vreemd dat die resultaat van die 'imageDirection / 8'-stelling 'n deel van die toestand is. Miskien moes hierdie stelling met iets anders vergelyk gewees het. libopenrct2 Observation Tower.cpp 38

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

Kom ons kyk van naderby. Uitdrukking beeldrigting/8 sal vals wees as beeldrigting is in die reeks van -7 tot 7. Tweede deel: (imageDirection / 8) != 3 tjeks beeldrigting omdat dit buite die reeks is: onderskeidelik van -31 tot -24 en van 24 tot 31. Dit lyk vir my nogal vreemd om nommers vir insluiting in 'n sekere reeks op hierdie manier na te gaan en, selfs al is daar geen fout in hierdie stukkie kode nie, sal ek aanbeveel om hierdie voorwaardes te herskryf om meer eksplisiet te wees. Dit sou die lewe baie makliker maak vir die mense wat hierdie kode sou lees en onderhou.

Waarskuwing N5

V587 'n Vreemde volgorde van opdragte van hierdie soort: A = B; B = A;. Kontroleer reëls: 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;
      ....
  }
  ....
}

Hierdie kodefragment is heel waarskynlik deur dekompilasie verkry. Toe, te oordeel aan die kommentaar wat gelaat is, is 'n deel van die nie-werkende kode verwyder. Daar is egter nog 'n paar operasies oor cursorId, wat ook nie veel sin maak nie.

Waarskuwing N6

V1004 [CWE-476] Die 'speler'-wyser is onveilig gebruik nadat dit teen nullptr geverifieer is. Kontroleer lyne: 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);                    // <=
  }
  ....
}

Hierdie kode is redelik maklik om reg te stel; jy hoef dit net 'n derde keer na te gaan speler by 'n nulwyser, of voeg dit by die liggaam van die voorwaardelike stelling. Ek sou die tweede opsie voorstel:

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

Waarskuwing N7

V547 [CWE-570] Uitdrukking 'name == nullptr' is altyd onwaar. 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));
    ....
  }
  ....
}

Jy kan in een klap ontslae raak van 'n moeilik leesbare reël kode en die probleem oplos deur te kyk vir nullptr. Ek stel voor dat u die kode soos volg verander:

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

Waarskuwing N8

V1048 [CWE-1164] Die 'ColumnHeaderPressedCurrentState' veranderlike is dieselfde waarde toegeken. libopenrct2ui CustomListView.cpp 510

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

Die kode lyk nogal vreemd. Dit lyk vir my of daar 'n tikfout was óf in die toestand óf wanneer die veranderlike hertoegewys is ColumnHeaderPressedCurrentState wat beteken valse.

Output

Soos ons kan sien, is die integrasie van die PVS-Studio statiese ontleder in jou TeamCity-projek redelik eenvoudig. Om dit te doen, is dit genoeg om net een klein konfigurasielêer te skryf. Deur die kode na te gaan, sal u probleme onmiddellik na montering kan identifiseer, wat sal help om dit uit te skakel wanneer die kompleksiteit en koste van veranderinge nog laag is.

PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die projek Open RollerCoaster Tycoon 2
As jy hierdie artikel met 'n Engelssprekende gehoor wil deel, gebruik asseblief die vertaalskakel: Vladislav Stolyarov. PVS-Studio en deurlopende integrasie: TeamCity. Ontleding van die Open RollerCoaster Tycoon 2-projek.

Bron: will.com

Voeg 'n opmerking