PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Unu di i scenarii più attuali per aduprà l'analizzatore PVS-Studio hè a so integrazione cù i sistemi CI. E ancu s'è l'analisi di un prughjettu PVS-Studio da quasi ogni sistema d'integrazione cuntinuu pò esse custruitu in uni pochi di cumandamenti, cuntinuemu à fà stu prucessu ancu più còmuda. PVS-Studio hà avà supportu per cunvertisce l'output di l'analizzatore in un furmatu per TeamCity - TeamCity Inspections Type. Videmu cumu si travaglia.

Informazioni nantu à u software utilizatu

PVS Studio - un analizzatore staticu di codice C, C++, C# è Java, cuncepitu per facilità u compitu di truvà è corregge diversi tipi d'errori. L'analizzatore pò esse usatu in Windows, Linux è macOS. In questu articulu avemu aduprà attivamente micca solu l'analizzatore stessu, ma ancu qualchi utilità da a so distribuzione.

CLMonitor - hè un servitore di monitoraghju chì monitorizza i lanciamenti di compilatori. Deve esse eseguitu immediatamente prima di cumincià à custruisce u vostru prughjettu. In u modu snooping, u servitore intercepterà e corse di tutti i compilatori supportati. Hè nutate chì sta utilità pò esse usata solu per analizà i prughjetti C/C++.

PlogConverter - una utilità per cunvertisce i rapporti di l'analizzatore in diversi formati.

Infurmazioni nantu à u prugettu in studiu

Pruvate sta funziunalità nantu à un esempiu praticu - analizemu u prughjettu OpenRCT2.

OpenRCT2 - una implementazione aperta di u ghjocu RollerCoaster Tycoon 2 (RCT2), espansione lu cù novi funzioni è corregge i bug. U gameplay gira intornu à custruisce è mantene un parcu di divertimentu chì cuntene passeggiate, buttreghi è facilità. U ghjucatore deve pruvà à fà un prufittu è mantene a bona reputazione di u parcu mentre mantene l'invitati felici. OpenRCT2 vi permette di ghjucà in u scenariu è in sandbox. I scenarii richiedenu chì u ghjucatore compie un compitu specificu in un tempu stabilitu, mentri Sandbox permette à u ghjucatore di custruisce un parcu più flessibile senza restrizioni o finanzii.

cutter

Per risparmià u tempu, prubabilmente saltaraghju u prucessu di stallazione è cumincià da u mumentu chì aghju u servitore TeamCity in esecuzione in u mo urdinatore. Avemu bisognu à andà à: localhost:{port specificatu durante u prucessu di stallazione} (in u mo casu, localhost:9090) è inserisce dati d'autorizazione. Dopu à l'entrata seremu salutati da:

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Cliccate nant'à u buttone Crea Prughjettu. Dopu, selezziunate Manually è compie i campi.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Dopu à appughjà u buttone creà, simu salutati da una finestra cù paràmetri.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Facemu cliccà Crea a cunfigurazione di custruzzione.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Riempite i campi è cliccate creà. Avemu vistu una finestra chì vi dumanda à selezziunà un sistema di cuntrollu di versione. Siccomu i fonti sò digià situatu in u locu, cliccate Skip.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Infine, andemu à i paràmetri di u prugettu.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Aghjunghjemu i passi di l'assemblea, per fà questu cliccate: Custruisce i passi -> Aggiungi un passu di custruzzione.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Quì avemu sceltu:

  • Runner type -> Command Line
  • Run -> Script Custom

Siccomu realiceremu analisi durante a compilazione di u prugettu, l'assemblea è l'analisi duveranu esse un passu, cusì compie u campu Scrittura Customizata:

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Fighjemu i passi individuali dopu. Hè impurtante chì caricate l'analizzatore, assemblendu u prughjettu, analizà, stende u rapportu è furmàttate solu undici linee di codice.

L'ultima cosa chì avemu da fà hè di stabilisce e variabili di l'ambienti, chì aghju delineatu alcune manere di migliurà a so leghjibilità. Per fà questu, andemu avanti: Parametri -> Aggiungi un novu paràmetru è aghjunghje trè variàbili:

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Tuttu ciò chì deve fà hè appughjà u buttone Run in l'angulu superiore dirittu. Mentre u prugettu hè assemblatu è analizatu, vi dicu di u script.

Scrittura diretta

Prima, avemu bisognu di scaricà l'ultima distribuzione PVS-Studio. Per questu usemu u gestore di pacchetti Chocolatey. Per quelli chì vulete sapè più nantu à questu, ci hè un currispundente un articulu:

choco install pvs-studio -y

In seguitu, lanciamu l'utilità di seguimentu di u prugettu CLMonitor.

%CLmon% monitor –-attach

Allora custruiremu u prughjettu cum'è una variabile d'ambiente MSB hè a strada per a versione di MSBuild chì aghju bisognu di custruisce

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

Entremu u login è a chjave di licenza per PVS-Studio:

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

Dopu chì a custruzione hè cumpleta, eseguite CLMonitor di novu per generà fugliali preprocessati è analisi statica:

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

Allora avemu aduprà una altra utilità da a nostra distribuzione. PlogConverter converte un rapportu da un formatu standard à un formatu specificu di TeamCity. Grazie à questu, pudemu vede direttamente in a finestra di creazione.

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

L'ultimu passu hè di vede u rapportu furmatu in stdout, induve serà pigliatu da u parser TeamCity.

type "C:tempptest.plog_TeamCity.txt"

Codice di script cumpletu:

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"

Intantu, l'assemblea è l'analisi di u prugettu hè stata cumpletata cù successu, pudemu andà à a tabulazione Projects è assicuratevi.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Avà andemu à cliccà Inspeczioni totaliper andà à vede u rapportu di l'analizzatore:

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
L'avvertimenti sò raggruppati per numeri di regula di diagnostica. Per navigà à traversu u codice, avete bisognu di cliccà nantu à u numeru di linea cù l'avvertimentu. Cliccà nant'à u puntu d'interrogazione in l'angulu superiore destra vi apre una nova tabulazione cù documentazione. Pudete ancu navigà à traversu u codice clicchendu nantu à u numeru di linea cù l'avvertimentu di l'analizzatore. A navigazione da un computer remoto hè pussibule quandu si usa SourceTreeRoot marcatore. Qualchissia chì hè interessatu in stu modu di funziunamentu di l'analizzatore pò familiarizà cù a sezione currispondente ducumentazione.

Vede i risultati di l'analizzatore

Avà chì avemu finitu di implementà è cunfigurà a custruzione, fighjemu un ochju à qualchi avvirtimenti interessanti truvati in u prughjettu chì guardemu.

Avvertimentu N1

V773 [CWE-401] L'eccezzioni hè stata lanciata senza liberà l'indicatore "risultatu". Una fuga di memoria hè pussibule. 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;
}

L'analizzatore hà rimarcatu un errore chì dopu l'assignazione dinamica di memoria in Crea un oggettu, quandu si trova una eccezzioni, a memoria ùn hè micca sguassata, è una fuga di memoria si trova.

Avvertimentu N2

V501 Ci sò sub-espressioni idèntici '(1ULL << WIDX_MONTH_BOX)' à a manca è à a diritta di u '|' operatore. 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),
  ....
};

Pochi persone altru ch'è un analizzatore staticu puderia passà sta prova di attenteness. Questu esempiu di copia-incolla hè bonu per precisamente per questu mutivu.

Avvertimenti N3

V703 Hè stranu chì u campu "bandiere" in a classa derivata "RCT12BannerElement" sovrascrive u campu in a classa base "RCT12TileElementBase". Verificate e linee: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

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

Di sicuru, l'usu di una variàbile cù u listessu nome in a classa di basa è in u discendenti ùn hè micca sempre un errore. In ogni casu, a tecnulugia di l'eredità stessu assume chì tutti i campi di a classa parenti sò prisenti in a classe di u zitellu. Dichjarà campi cù u listessu nome in l'eredi, intruducemu cunfusione.

Avvertimentu N4

V793 Hè stranu chì u risultatu di a dichjarazione "imageDirection / 8" hè una parte di a cundizione. Forsi, sta dichjarazione duveria esse paragunata cù qualcosa d'altru. libopenrct2 ObservationTower.cpp 38

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

Fighjemu un ochju più vicinu. Spressione Direzzione image/8 serà falsu se Direzzione di l'imaghjini hè in u range da -7 à 7. Seconda parte: (direzzione di l'imaghjini / 8) != 3 cuntrolli Direzzione di l'imaghjini per esse fora di a gamma: da -31 à -24 è da 24 à 31, rispettivamente. Mi pare abbastanza stranu per verificà i numeri per l'inclusione in un certu intervallu in questu modu è, ancu s'ellu ùn ci hè micca errore in questu pezzu di codice, ricumandemu di riscrittura di sti cundizioni per esse più espliciti. Questu faria a vita assai più faciule per e persone chì leghjenu è mantene stu codice.

Avvertimentu N5

V587 Una sequenza strana di assignazioni di stu tipu: A = B; B = A;. Verificate e linee: 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;
      ....
  }
  ....
}

Stu frammentu di codice hè statu più prubabilmente ottenutu da decompilation. Allora, à ghjudicà da u cumentu lasciatu, una parte di u codice chì ùn funziona micca hè stata eliminata. Tuttavia, ci sò sempre un paru di operazioni cursorId, chì ancu ùn hà micca assai sensu.

Avvertimentu N6

V1004 [CWE-476] L'indicatore "player" hè statu utilizatu in modu inseguru dopu chì hè statu verificatu contru nullptr. Verificate e linee: 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);                    // <=
  }
  ....
}

Stu codice hè abbastanza faciule da curregà; basta à verificà una terza volta jocaturi à un puntatore nulu, o aghjunghje à u corpu di a dichjarazione condicionale. Suggeriu a seconda opzione:

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

Avvertimentu N7

V547 [CWE-570] L'espressione 'name == nullptr' hè sempre falsa. 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));
    ....
  }
  ....
}

Pudete caccià una linea di codice difficiuli di leghje in un colpu è risolve u prublema cù a verificazione di nullptr. Suggeriu di cambià u codice cum'è seguente:

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

Avvertimentu N8

V1048 [CWE-1164] A variabile "ColumnHeaderPressedCurrentState" hè stata assignata u listessu valore. libopenrct2ui CustomListView.cpp 510

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

U codice pare abbastanza stranu. Mi pari chì ci era un typo o in a cundizione o quandu ri-assignà a variàbile ColumnHeaderPressedCurrentState significatu sbagliate.

cunchiusioni

Comu pudemu vede, l'integrazione di l'analizzatore staticu PVS-Studio in u vostru prughjettu TeamCity hè abbastanza simplice. Per fà questu, hè abbastanza à scrive solu un picculu schedariu di cunfigurazione. A verificazione di u codice vi permetterà di identificà i prublemi immediatamente dopu l'assemblea, chì aiutarà à eliminà quandu a cumplessità è u costu di i cambiamenti sò sempre bassu.

PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prugettu Open RollerCoaster Tycoon 2
Se vulete sparte stu articulu cù un publicu anglofonu, per piacè utilizate u ligame di traduzzione: Vladislav Stolyarov. PVS-Studio è Integrazione Continua: TeamCity. Analisi di u prughjettu Open RollerCoaster Tycoon 2.

Source: www.habr.com

Add a comment