PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Ien fan 'e meast aktuele senario's foar it brûken fan de PVS-Studio-analysator is syn yntegraasje mei CI-systemen. En hoewol't de analyze fan in PVS-Studio projekt út hast alle trochgeande yntegraasje systeem kin wurde boud yn mar in pear kommando's, wy bliuwe te meitsje dit proses noch handiger. PVS-Studio hat no stipe foar it konvertearjen fan analysatorútfier yn in formaat foar TeamCity - TeamCity Inspections Type. Litte wy sjen hoe't it wurket.

Ynformaasje oer de brûkte software

PVS-Studio - in statyske analysator fan C, C++, C# en Java-koade, ûntworpen om de taak te fasilitearjen om ferskate soarten flaters te finen en te korrigearjen. De analyzer kin brûkt wurde op Windows, Linux en macOS. Yn dit artikel sille wy aktyf brûke net allinich de analysator sels, mar ek guon nutsbedriuwen út syn distribúsje.

CLMonitor - is in tafersjochtsjinner dy't de lansearringen fan kompilator kontrolearret. It moat fuortendaliks útfierd wurde foardat jo begjinne mei it bouwen fan jo projekt. Yn snooping modus sil de tsjinner runen fan alle stipe kompilers ûnderskeppe. It is de muoite wurdich op te merken dat dit hulpprogramma allinich kin wurde brûkt om C / C ++ projekten te analysearjen.

PlogConverter - in hulpprogramma foar it konvertearjen fan analysatorrapporten yn ferskate formaten.

Ynformaasje oer it projekt ûnder stúdzje

Litte wy dizze funksjonaliteit besykje op in praktysk foarbyld - lit ús it OpenRCT2-projekt analysearje.

OpenRCT2 - in iepen ymplemintaasje fan it spultsje RollerCoaster Tycoon 2 (RCT2), útwreidzje it mei nije funksjes en reparearje bugs. Gameplay draait om it bouwen en ûnderhâlden fan in pretpark mei ritten, winkels en foarsjenningen. De spiler moat besykje in winst en behâlden it park syn goede reputaasje wylst hâlden gasten lokkich. OpenRCT2 lit jo spielje yn sawol senario as sânbak. Senario's fereaskje dat de spiler in spesifike taak binnen in bepaalde tiid foltôget, wylst Sandbox de spiler in fleksibeler park kin bouwe sûnder beheiningen of finânsjes.

oanpassing

Om tiid te besparjen, sil ik wierskynlik it ynstallaasjeproses oerslaan en begjinne fan it momint dat ik de TeamCity-tsjinner op myn kompjûter haw. Wy moatte gean nei: localhost:{poarte oantsjutte tidens it ynstallaasjeproses} (yn myn gefal, localhost:9090) en autorisaasjegegevens ynfiere. Nei it ynfieren wurde wy begroete troch:

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Klikje op de knop Project oanmeitsje. Selektearje dan Hânmjittich en folje de fjilden yn.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Nei it drukken op de knop Meitsje, wy wurde begroete troch in finster mei ynstellings.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Litte wy klikke Meitsje build konfiguraasje.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Folje de fjilden yn en klikje Meitsje. Wy sjogge in finster dat jo freget om in ferzjekontrôlesysteem te selektearjen. Om't de boarnen al lokaal lizze, klikje jo Oerslaan.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
As lêste geane wy ​​troch nei de projektynstellingen.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Litte wy montagestappen tafoegje, klikje om dit te dwaan: Boustappen -> Boustap taheakje.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Hjir kieze wy:

  • Runner type -> Kommandorigel
  • Run -> Oanpaste skript

Om't wy analyse sille útfiere tidens projektkompilaasje, moatte gearstalling en analyse ien stap wêze, dus folje it fjild yn Oanpaste skript:

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Wy sille letter nei yndividuele stappen sjen. It is wichtich dat it laden fan de analysator, it gearstallen fan it projekt, it analysearjen, it útfieren fan it rapport en it opmeitsjen fan it mar alve rigels koade nimt.

It lêste wat wy moatte dwaan is de omjouwingsfariabelen ynstelle, dy't ik guon manieren haw sketst om har lêsberens te ferbetterjen. Om dit te dwaan, litte wy trochgean: Parameters -> Nije parameter tafoegje en foegje trije fariabelen ta:

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Alles wat jo hoege te dwaan is op de knop drukke run yn 'e rjochter boppeste hoeke. Wylst it projekt wurdt gearstald en analysearre, Ik sil fertelle jo oer it skript.

Direkt skript

Earst moatte wy de lêste PVS-Studio-distribúsje downloade. Dêrfoar brûke wy de Chocolatey-pakketbehearder. Foar wa't hjir mear oer witte wol, is der in oerienkommende artikel:

choco install pvs-studio -y

Litte wy dan it CLMonitor-projekt foar it folgjen fan it trackingprogramma lansearje.

%CLmon% monitor –-attach

Dan sille wy it projekt bouwe as in omjouwingsfariabele MSB is it paad nei de ferzje fan MSBuild ik moat bouwen

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

Litte wy de oanmeld- en lisinsjekaai ynfiere foar PVS-Studio:

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

Nei it bouwen is foltôge, rinne CLMonitor opnij om foarbewurke bestannen en statyske analyse te generearjen:

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

Dan sille wy in oar nut brûke fan ús distribúsje. PlogConverter konvertearret in rapport fan in standertformaat nei in TeamCity-spesifike opmaak. Hjirmei sille wy it direkt kinne besjen yn it boufinster.

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

De lêste stap is om it opmakke rapport yn te werjaan stdout, wêr't it wurdt ophelle troch de TeamCity-parser.

type "C:tempptest.plog_TeamCity.txt"

Folsleine skriptkoade:

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"

Yn 'e tuskentiid is de gearstalling en analyse fan it projekt mei súkses foltôge, kinne wy ​​​​gean nei it ljepblêd Projects en meitsje der wis fan.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
No litte wy op klikke Ynspeksjes Totaalom te gean nei it besjen fan it analysatorrapport:

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
Warskôgings wurde groepearre troch diagnostyske regelnûmers. Om troch de koade te navigearjen, moatte jo klikke op it linenûmer mei de warskôging. Klikje op it fraachteken yn 'e rjochter boppeste hoeke sil jo in nije ljepper iepenje mei dokumintaasje. Jo kinne ek navigearje troch de koade troch te klikken op it rigelnûmer mei de warskôging foar analysator. Navigaasje fan in kompjûter op ôfstân is mooglik by it brûken SourceTreeRoot marker. Elkenien dy't ynteressearre is yn dizze modus fan wurking fan 'e analyzer kin harsels fertroud meitsje mei de oerienkommende seksje dokumintaasje.

Besjoch de resultaten fan 'e analysator

No't wy klear binne mei it ynsetten en konfigurearjen fan 'e build, litte wy ris sjen nei wat nijsgjirrige warskôgings fûn yn it projekt wêr't wy nei sjogge.

Warskôging N1

V773 [CWE-401] De útsûndering waard smiten sûnder de 'resultaat'-oanwizer frij te litten. In ûnthâld lek is mooglik. 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;
}

De analysator opmurken in flater dy't nei dynamysk allocating ûnthâld yn CreateObject, as in útsûndering optreedt, it ûnthâld wurdt net wiske, en in ûnthâld lek optreedt.

Warskôging N2

V501 D'r binne identike sub-ekspresjes '(1ULL << WIDX_MONTH_BOX)' links en rjochts fan '|' operator. 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),
  ....
};

In pear minsken oars as in statyske analysator koene dizze attentiviteitstest trochjaan. Dit copy-paste-foarbyld is krekt om dizze reden goed.

Warskôgings N3

V703 It is nuver dat it fjild 'flaggen' yn 'e ôflaat klasse 'RCT12BannerElement' fjild yn 'e basisklasse 'RCT12TileElementBase' oerskriuwt. Kontrolearje rigels: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

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

Fansels is it brûken fan in fariabele mei deselde namme yn 'e basisklasse en yn' e neisiet net altyd in flater. Erfskiptechnology sels giet der lykwols fanút dat alle fjilden fan 'e âlderklasse oanwêzich binne yn' e bernklasse. Troch fjilden mei deselde namme yn 'e erfgenamt te ferklearjen, meitsje wy betizing.

Warskôging N4

V793 It is nuver dat it resultaat fan 'e ferklearring 'imageDirection / 8' diel is fan 'e betingst. Miskien hie dizze útspraak mei wat oars fergelike wurde moatten. libopenrct2 ObservationTower.cpp 38

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

Lit ús ris efkes neier sjen. Útdrukking imageDirection/8 sil wêze falsk as imageDirection leit yn it berik fan -7 oant 7. Twadde diel: (imageDirection / 8) != 3 kontrôles imageDirection om bûten it berik te wêzen: respektivelik fan -31 oant -24 en fan 24 oant 31. It liket my frij frjemd om nûmers te kontrolearjen foar opname yn in bepaald berik op dizze manier en, sels as d'r gjin flater is yn dit stikje koade, soe ik riede om dizze betingsten opnij te skriuwen om eksplisyt te wêzen. Dit soe it libben folle makliker meitsje foar de minsken dy't dizze koade lêze en ûnderhâlde.

Warskôging N5

V587 In ûneven folchoarder fan opdrachten fan dit soarte: A = B; B = A;. Kontrolearje rigels: 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;
      ....
  }
  ....
}

Dit koadefragmint waard nei alle gedachten krigen troch dekompilaasje. Dan, te beoardieljen nei de opmerking lofts, waard in diel fan 'e net-wurkende koade fuortsmiten. Der binne lykwols noch in pear operaasjes oer cursorId, dy't ek net folle sin hawwe.

Warskôging N6

V1004 [CWE-476] De 'spiler' oanwizer waard ûnfeilich brûkt neidat it waard ferifiearre tsjin nullptr. Kontrolearje rigels: 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);                    // <=
  }
  ....
}

Dizze koade is frij maklik te korrigearjen; jo moatte it gewoan in tredde kear kontrolearje spiler oan in nul-oanwizer, of heakje it ta oan it lichem fan 'e betingsten. Ik soe de twadde opsje foarstelle:

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

Warskôging N7

V547 [CWE-570] Ekspresje 'namme == nullptr' is altyd falsk. 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));
    ....
  }
  ....
}

Jo kinne in hurd te lêzen rigel koade yn ien klap kwytreitsje en it probleem oplosse troch te kontrolearjen foar nullptr. Ik stel foar om de koade as folgjend te feroarjen:

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

Warskôging N8

V1048 [CWE-1164] De fariabele 'ColumnHeaderPressedCurrentState' waard deselde wearde tawiisd. libopenrct2ui CustomListView.cpp 510

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

De koade sjocht der hiel nuver út. It liket my ta dat der in typflater wie yn de betingst of by it opnij tawizen fan de fariabele ColumnHeaderPressedCurrentState wearden falsk.

konklúzje

Lykas wy kinne sjen, is it yntegrearjen fan de statyske analysator PVS-Studio yn jo TeamCity-projekt frij ienfâldich. Om dit te dwaan is it genôch om mar ien lyts konfiguraasjetriem te skriuwen. Troch de koade te kontrolearjen kinne jo problemen fuortendaliks nei de gearstalling identifisearje, wat sil helpe om se te eliminearjen as de kompleksiteit en kosten fan feroaringen noch leech binne.

PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2
As jo ​​​​dit artikel wolle diele mei in Ingelsktalig publyk, brûk dan de oersettingskeppeling: Vladislav Stolyarov. PVS-Studio en trochgeande yntegraasje: TeamCity. Analyse fan it projekt Open RollerCoaster Tycoon 2.

Boarne: www.habr.com

Add a comment