PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Salah sahiji skenario anu paling ayeuna pikeun ngagunakeun analisa PVS-Studio nyaéta integrasina sareng sistem CI. Sarta sanajan analisa hiji proyék PVS-Studio tina ampir sagala sistem integrasi kontinyu bisa diwangun kana ngan sababaraha Paréntah, urang neruskeun prosés ieu malah leuwih merenah. PVS-Studio ayeuna gaduh dukungan pikeun ngarobih kaluaran analisa kana format pikeun TeamCity - TeamCity Inspections Type. Hayu urang tingali kumaha gawéna.

Émbaran ngeunaan software dipaké

PVS Studio - a analyzer statik C, C ++, C # jeung kode Java, dirancang pikeun mempermudah tugas manggihan tur koréksi rupa-rupa kasalahan. Analisa tiasa dianggo dina Windows, Linux sareng macOS. Dina artikel ieu kami baris aktip ngagunakeun teu ukur analyzer sorangan, tapi ogé sababaraha Utiliti ti distribusi na.

CLMonitor - mangrupikeun server ngawaskeun anu ngawaskeun peluncuran kompiler. Éta kedah dijalankeun langsung sateuacan ngamimitian ngawangun proyék anjeun. Dina modeu snooping, server bakal intercept ngajalankeun sadaya compiler dirojong. Perhatos yén utilitas ieu ngan ukur tiasa dianggo pikeun nganalisis proyék C / C ++.

PlogConverter - utilitas pikeun ngarobih laporan analisa kana format anu béda.

Inpormasi ngeunaan proyék anu ditalungtik

Hayu urang coba fungsionalitas ieu dina conto praktis - hayu urang nganalisis proyék OpenRCT2.

OpenRCT2 - palaksanaan kabuka tina kaulinan RollerCoaster Tycoon 2 (RCT2), dilegakeun ku fungsi anyar sareng ngalereskeun bug. Midangkeun revolves sabudeureun ngawangun jeung ngajaga hiji taman hiburan ngandung rides, toko, jeung fasilitas. Pamaén kudu nyobaan nyieun untung jeung ngajaga reputasi alus taman bari tetep sémah senang. OpenRCT2 ngamungkinkeun anjeun maén dina skenario sareng kotak pasir. Skenario merlukeun pamaén pikeun ngarengsekeun tugas husus dina waktu set, bari Sandbox ngamungkinkeun pamuter ka ngawangun taman leuwih fleksibel tanpa palarangan atawa finances.

carana ngatur

Dina raraga ngahemat waktos, abdi sigana bakal skip prosés instalasi tur mimitian ti momen nalika kuring boga server TeamCity jalan dina komputer kuring. Urang kudu indit ka: localhost: {port husus salila prosés instalasi} (bisi kuring, localhost: 9090) jeung asupkeun data otorisasina. Saatos lebet urang bakal disambut ku:

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Pencét kana tombol Jieun Proyék. Teras, pilih Sacara manual sareng eusian sawah.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Sanggeus mencet tombol nyiptakeun, urang disambut ku jandela kalawan setelan.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Hayu urang klik Jieun konfigurasi ngawangun.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Eusian widang teras klik nyiptakeun. Kami ningali jandela naroskeun anjeun milih sistem kontrol versi. Kusabab sumberna parantos aya sacara lokal, klik ngaliwatan.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Tungtungna, urang ngaléngkah ka setélan proyék.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Hayu urang tambahkeun léngkah assembly, pikeun ngalakukeun ieu klik: Léngkah ngawangun -> Tambahkeun léngkah ngawangun.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Di dieu urang milih:

  • Tipe runner -> Jalur Komando
  • Jalankeun -> Custom Script

Kusabab urang bakal ngalakukeun analisis salila kompilasi proyék, assembly jeung analisis kedah hiji hambalan, jadi eusian lapangan Script custom:

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Urang bakal ningali léngkah individu engké. Kadé loading analyzer, assembling proyék, analisa eta, outputting laporan jeung pormat nu diperlukeun ngan sabelas garis kode.

Hal anu terakhir anu kedah urang laksanakeun nyaéta nyetél variabel lingkungan, anu ku kuring parantos digariskeun sababaraha cara pikeun ningkatkeun kabacana. Jang ngalampahkeun ieu, hayu urang ngaléngkah: Parameter -> Tambahkeun parameter anyar sareng tambahkeun tilu variabel:

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Sadaya anu anjeun kedah laksanakeun nyaéta pencét tombol lalumpatan di pojok katuhu luhur. Nalika proyékna dirakit sareng dianalisis, kuring bakal nyarioskeun ka anjeun ngeunaan naskah.

Langsung naskah

Kahiji, urang kudu ngundeur PVS-Studio distribution panganyarna. Pikeun ieu kami nganggo manajer pakét Chocolatey. Pikeun anu hoyong terang langkung seueur ngeunaan ieu, aya anu saluyu artikel:

choco install pvs-studio -y

Salajengna, hayu urang ngaluncurkeun utilitas pelacak ngawangun proyék CLMonitor.

%CLmon% monitor –-attach

Teras we bakal ngawangun proyék salaku variabel lingkungan MSB nyaeta jalur ka versi MSBuild Abdi peryogi ngawangun

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

Hayu urang lebetkeun login sareng konci lisénsi pikeun PVS-Studio:

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

Saatos ngawangun réngsé, jalankeun CLMonitor deui pikeun ngahasilkeun file anu tos diprosés sareng analisa statik:

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

Teras kami bakal nganggo utilitas anu sanés tina distribusi kami. PlogConverter ngarobih laporan tina format standar kana format khusus TeamCity. Hatur nuhun kana ieu, urang bakal tiasa ningali éta langsung dina jandela ngawangun.

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

Léngkah terakhir nyaéta ningalikeun laporan anu diformat dina stdout, dimana éta bakal dijemput ku parser TeamCity.

type "C:tempptest.plog_TeamCity.txt"

Kode naskah lengkep:

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"

Samentara éta, assembly jeung analisis proyék geus réngsé hasil, urang tiasa buka tab proyék jeung pastikeun eta.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Ayeuna hayu urang klik dina Inspections Totalpikeun ningali laporan analisa:

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Warnings dikelompokeun ku angka aturan diagnostik. Pikeun napigasi ngaliwatan kode, Anjeun kudu klik dina nomer garis kalawan peringatan. Ngaklik tanda tanya di pojok katuhu luhur bakal muka anjeun tab anyar sareng dokuméntasi. Anjeun oge bisa napigasi ngaliwatan kode ku ngaklik dina nomer garis kalawan warning analyzer. Napigasi tina komputer jauh tiasa nalika nganggo SourceTreeRoot pananda. Saha waé anu kabetot dina modeu operasi analyzer ieu tiasa familiarize diri sareng bagian anu saluyu dokuméntasi.

Ningali hasil analis

Ayeuna urang parantos ngalaksanakeun sareng ngonpigurasikeun ngawangun, hayu urang tingali sababaraha peringatan anu pikaresepeun anu aya dina proyék anu urang tingali.

Perhatosan N1

V773 [CWE-401] Iwal ieu dialungkeun tanpa ngaleupaskeun pointer 'hasil'. A bocor memori mungkin. 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;
}

analyzer The noticed kasalahan anu sanggeus dinamis allocating memori dina CreateObject, nalika aya pengecualian, mémori henteu diberesihan, sareng kabocoran mémori lumangsung.

Perhatosan N2

V501 Aya sub-eksprési idéntik '(1ULL << WIDX_MONTH_BOX)' ka kénca jeung ka katuhu tina '|' 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),
  ....
};

Sababaraha urang salian ti analisa statik tiasa lulus tés attentiveness ieu. Conto salinan-témpél ieu saé pikeun alesan ieu.

Perhatosan N3

V703 Aneh yén widang 'bendera' dina kelas turunan 'RCT12BannerElement' nimpa widang dina kelas dasar 'RCT12TileElementBase'. Pariksa garis: RCT12.h:570, RCT12.h:259. libopenrct2 RCT12.h 570

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

Tangtosna, ngagunakeun variabel sareng nami anu sami dina kelas dasar sareng turunan henteu salawasna kasalahan. Sanajan kitu, téhnologi warisan sorangan nganggap yén sagala widang kelas indungna hadir dina kelas anak. Ku ngadéklarasikeun widang anu ngaranna sarua dina ahli waris, urang ngenalkeun kabingungan.

Perhatosan N4

V793 Aneh yén hasil tina pernyataan 'imageDirection / 8' mangrupikeun bagian tina kaayaan. Panginten, pernyataan ieu kedah dibandingkeun sareng anu sanés. libopenrct2 ObservationTower.cpp 38

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

Hayu urang nempo leuwih deukeut. Ekspresi gambarArah/8 bakal palsu lamun gambarArah aya dina rentang ti -7 nepi ka 7. Bagian kadua: (gambarArah / 8) != 3 cék gambarArah keur di luar rentang: ti -31 nepi ka -24 jeung ti 24 nepi ka 31, mungguh. Sigana rada aneh mun kuring mariksa angka pikeun citakan dina rentang tangtu ku cara kieu na, sanajan euweuh kasalahan dina sapotong kode ieu, Abdi nyarankeun nulis balik kaayaan ieu janten langkung eksplisit. Ieu bakal ngagampangkeun kahirupan pikeun jalma anu bakal maca sareng ngajaga kode ieu.

Perhatosan N5

V587 Runtuyan ganjil tina tugas sapertos kieu: A = B; B = A;. Pariksa garis: 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;
      ....
  }
  ....
}

Fragmén kode ieu paling dipikaresep diala ku dekompilasi. Lajeng, ditilik ku comment ditinggalkeun, bagian tina kode non-kerja dihapus. Tapi, masih aya sababaraha operasi anu tinggaleun kursorId, nu ogé teu make akal pikiran.

Perhatosan N6

V1004 [CWE-476] The 'pamuter' pointer dipaké unsafely sanggeus diverifikasi ngalawan nullptr. Pariksa garis: 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);                    // <=
  }
  ....
}

Kode ieu rada gampang dibenerkeun; anjeun ngan ukur kedah pariksa deui katilu kalina pamaen ka pointer null, atawa tambahkeun ka awak pernyataan kondisional. Abdi nyarankeun pilihan kadua:

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

Perhatosan N7

V547 [CWE-570] Babasan 'ngaran == nullptr' sok palsu. 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));
    ....
  }
  ....
}

Anjeun tiasa nyingkirkeun garis kode anu hese dibaca dina hiji waktos sareng ngarengsekeun masalah sareng mariksa nullptr. Abdi nyarankeun ngarobih kode sapertos kieu:

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

Perhatosan N8

V1048 [CWE-1164] Variabel 'ColumnHeaderPressedCurrentState' dipasihan nilai anu sami. libopenrct2ui CustomListView.cpp 510

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

Kodeu Sigana rada aneh. Sigana mah aya typo boh dina kaayaan atawa nalika ulang assigning variabel ColumnHeaderPressedCurrentState harti palsu.

kacindekan

Sakumaha anu urang tingali, ngahijikeun analisa statik PVS-Studio kana proyék TeamCity anjeun cukup saderhana. Jang ngalampahkeun ieu, cukup nulis ngan hiji file konfigurasi leutik. Mariksa kode bakal ngidinan Anjeun pikeun ngaidentipikasi masalah langsung saatos assembly, nu bakal nulungan ngaleungitkeun aranjeunna nalika pajeulitna sarta biaya parobahan masih low.

PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2
Upami anjeun hoyong ngabagikeun tulisan ieu ka pamiarsa anu nyarios basa Inggris, mangga nganggo tautan tarjamahan: Vladislav Stolyarov. PVS-Studio sarta Integrasi kontinyu: TeamCity. Analisis proyék Open RollerCoaster Tycoon 2.

sumber: www.habr.com

Tambahkeun komentar