PVS-Studio sekarang di Chocolatey: memeriksa Chocolatey dari Azure DevOps

Gambar 4

Kami terus membuat menggunakan PVS-Studio lebih nyaman. Analiser kami sekarang tersedia di Chocolatey, manajer paket untuk Windows. Kami percaya bahwa ini akan memfasilitasi penyebaran PVS-Studio, khususnya, dalam layanan cloud. Agar tidak melangkah terlalu jauh, periksa kode sumber Chocolatey yang sama. Sistem CI akan menjadi Azure DevOps.

Berikut adalah daftar artikel kami yang lain tentang integrasi cloud:


Saya menyarankan Anda untuk memperhatikan artikel pertama tentang integrasi dengan Azure DevOps, karena dalam hal ini beberapa poin dihilangkan agar tidak digandakan.

Jadi, pahlawan artikel ini:

PVS-Studio adalah alat analisis kode statis yang dirancang untuk mendeteksi kesalahan dan kerentanan potensial dalam program yang ditulis dalam C, C ++, C # dan Java. Ini bekerja pada sistem 64-bit pada Windows, Linux, dan macOS, dan dapat menganalisis kode yang dirancang untuk platform ARM 32-bit, 64-bit, dan tertanam. Jika ini adalah pertama kalinya Anda mencoba analisis kode statis untuk memverifikasi proyek Anda, kami sarankan Anda membaca artikel tentang cara cepat melihat peringatan paling menarik dari PVS-Studio dan mengevaluasi kemampuan alat ini.

Azure DevOps- Seperangkat layanan cloud, bersama-sama mencakup seluruh proses pengembangan. Platform ini mencakup alat-alat seperti Pipa Azure, Papan Azure, Artefak Azure, Azure Repos, Azure Test Plans, yang mempercepat proses pembuatan perangkat lunak dan meningkatkan kualitasnya.

Chocolatey adalah pengelola paket sumber terbuka untuk Windows. Tujuan dari proyek ini adalah untuk mengotomatiskan seluruh siklus hidup perangkat lunak dari instalasi hingga memperbarui dan menghapus instalasi pada sistem operasi Windows.

Tentang menggunakan Chocolatey


Anda dapat melihat cara menginstal manajer paket dengan tautan ini . Dokumentasi lengkap tentang pemasangan alat analisis tersedia di tautan di bagian “Instalasi menggunakan manajer paket Chocolatey”. Saya akan mengulangi secara singkat beberapa poin dari sana.

Perintah untuk menginstal versi analisa terbaru:

choco install pvs-studio

Perintah untuk menginstal versi spesifik dari paket PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Secara default, hanya inti penganalisa yang dipasang - komponen Inti. Semua flag lainnya (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) dapat dilewati menggunakan --package-parameter.

Contoh perintah yang akan menginstal penganalisis dengan plug-in untuk Visual Studio 2019:

choco install pvs-studio --package-parameters="'/MSVS2019'"

Sekarang mari kita lihat contoh penggunaan penganalisis yang nyaman di bawah Azure DevOps.

Kustomisasi


Saya mengingatkan Anda bahwa ada artikel terpisah tentang masalah seperti mendaftarkan akun, membuat Saluran Pipa, dan menyinkronkan akun dengan proyek di repositori di GitHub . Pengaturan kami akan segera dimulai dengan menulis file konfigurasi.

Pertama, konfigurasikan pemicu untuk memicu, yang menunjukkan bahwa kami hanya menjalankan perubahan di cabang master :

trigger:
- master

Selanjutnya, kita perlu memilih mesin virtual. Saat ini, itu akan menjadi agen yang di-host oleh Microsoft dengan Windows Server 2019 dan Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Mari kita beralih ke isi file konfigurasi (blok langkah ). Terlepas dari kenyataan bahwa perangkat lunak sewenang-wenang tidak dapat diinstal di mesin virtual, saya tidak menambahkan wadah Docker. Kami dapat menambahkan Chocolatey sebagai ekstensi untuk Azure DevOps. Untuk melakukan ini, klik tautannya . Klik Dapatkan gratis . Selanjutnya, jika Anda sudah diotorisasi, cukup pilih akun Anda, dan jika tidak, maka lakukan hal yang sama setelah otorisasi.

Gambar 2


Di sini Anda perlu memilih di mana kami akan menambahkan ekstensi, dan klik tombol Instal .

Gambar 5


Setelah instalasi berhasil, klik Lanjutkan ke organisasi :

Gambar 9


Sekarang Anda dapat melihat templat untuk tugas Chocolatey di jendela tugas saat mengedit file konfigurasi azure-pipelines.yml:

Gambar 6


Klik pada Chocolatey dan lihat daftar bidang:

Gambar 7


Di sini kita perlu memilih instal di bidang perintah. Dalam Nama File Nuspec, tentukan nama paket yang diinginkan - pvs-studio. Jika Anda tidak menentukan versi, yang terakhir akan diinstal, yang sepenuhnya sesuai dengan kami. Klik pada tombol add dan lihat tugas yang terbentuk di file konfigurasi.

steps:
- task: ChocolateyCommand@0
  inputs:
    command: 'install'
    installPackageId: 'pvs-studio'

Selanjutnya, mari kita beralih ke bagian utama dari file kita:

- task: CmdLine@2
  inputs:
    script: 

Sekarang kita perlu membuat file dengan lisensi analyzer. Di sini, PVSNAME dan PVSKEY adalah nama-nama variabel yang nilainya kami tentukan dalam pengaturan. Mereka akan menyimpan login dan kunci lisensi PVS-Studio. Untuk mengatur nilainya, buka menu Variables-> Variabel baru . Buat variabel PVSNAME untuk login dan PVSKEY untuk kunci analisa. Ingatlah untuk memeriksa kotak centang Jaga nilai rahasia ini untuk PVSKEY . Kode Tim:

all "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials 
–u $(PVSNAME) –n $(PVSKEY)

Mari kita membangun proyek menggunakan file bat yang terletak di repositori:

all build.bat

Buat folder tempat file dengan hasil kerja penganalisa akan terletak:

all mkdir PVSTestResults

Jalankan analisis proyek:

all "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
–t .\src\chocolatey.sln –o .\PVSTestResults\Choco.plog 

Kami mengonversi laporan kami ke dalam format html menggunakan utilitas Plogonverter:

all "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" 
–t html –o \PVSTestResults\ .\PVSTestResults\Choco.plog

Sekarang Anda perlu membuat tugas agar Anda dapat mengunggah laporan.

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    condition: always()

File konfigurasi lengkap terlihat seperti ini:

trigger:
- master

pool:
  vmImage: 'windows-latest'

steps:
- task: ChocolateyCommand@0
  inputs:
    command: 'install'
    installPackageId: 'pvs-studio'

- task: CmdLine@2
  inputs:
    script: |
      call "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
      credentials –u $(PVSNAME) –n $(PVSKEY)
      call build.bat
      call mkdir PVSTestResults
      call "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
      –t .\src\chocolatey.sln –o .\PVSTestResults\Choco.plog
      call "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" 
      –t html –o .\PVSTestResults\ .\PVSTestResults\Choco.plog

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    condition: always()

Klik Simpan-> Simpan-> Jalankan untuk memulai tugas. Bongkar laporan dengan masuk ke tab tugas.

Angka 8



Proyek Chocolatey berisi total 37.615 baris kode C #. Pertimbangkan beberapa kesalahan yang ditemukan.

Hasil Validasi


Peringatan N1

Analyzer Warning: V3005 Variabel 'Penyedia' ditugaskan untuk dirinya sendiri. CrytpoHashProviderSpecs.cs 38

public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
  ....
  protected CryptoHashProvider Provider;
  ....
  public override void Context()
  {
    Provider = Provider = new CryptoHashProvider(FileSystem.Object);
  }
}

Penganalisa menemukan penugasan variabel untuk dirinya sendiri, yang tidak masuk akal. Kemungkinan besar, di tempat salah satu variabel ini harus ada yang lain. Ya, atau ini salah ketik, dan tugas yang tidak perlu bisa dihapus begitu saja.

Peringatan N2

Analyzer Warning: V3093 [CWE-480] Operator '&' mengevaluasi kedua operan. Mungkin operator hubung singkat &&& harus digunakan sebagai gantinya. Platform.cs 64

public static PlatformType get_platform()
{
  switch (Environment.OSVersion.Platform)
  {
    case PlatformID.MacOSX:
    {
      ....
    }
    case PlatformID.Unix:
    if(file_system.directory_exists("/Applications")
      & file_system.directory_exists("/System")
      & file_system.directory_exists("/Users")
      & file_system.directory_exists("/Volumes"))
      {
        return PlatformType.Mac;
      }
        else
          return PlatformType.Linux;
    default:
      return PlatformType.Windows;
  }
}

Perbedaan antara operator & & operator & adalah bahwa jika sisi kiri ekspresi salah , maka sisi kanan masih akan dihitung, yang dalam hal ini menyiratkan panggilan tambahan ke metode system.directory_exists .

Dalam fragmen ini, ini adalah cacat kecil. Ya, kondisi ini dapat dioptimalkan dengan mengganti operator & dengan operator&&, tetapi dari sudut pandang praktis, ini tidak mempengaruhi apa pun. Namun, dalam kasus lain, kebingungan antara & dan && dapat menyebabkan masalah serius ketika sisi kanan ekspresi akan berfungsi dengan nilai yang salah / tidak valid. Misalnya, dalam kumpulan kesalahan yang terdeteksi oleh diagnostik V3093 , ada kasus seperti itu:

if ((k < nct) & (s[k] != 0.0))

Bahkan jika indeks k tidak benar, itu akan digunakan untuk mengakses elemen array. Akibatnya, IndexOutOfRangeException akan dilempar .

Peringatan N3, N4

Analyzer Peringatan: V3022 [CWE-571] Ekspresi 'shortPrompt' selalu benar. InteractivePrompt.cs 101
Peringatan Analyzer: V3022 [CWE-571] Ekspresi 'shortPrompt' selalu benar. InteractivePrompt.cs 105

public static string 
prompt_for_confirmation(.... bool shortPrompt = false, ....)
{
  ....
  if (shortPrompt)
  {
    var choicePrompt = choice.is_equal_to(defaultChoice) //1
    ?
    shortPrompt //2
    ?
    "[[{0}]{1}]".format_with(choice.Substring(0, 1).ToUpperInvariant(), //3
    choice.Substring(1,choice.Length - 1))
    :
    "[{0}]".format_with(choice.ToUpperInvariant()) //0
    : 
    shortPrompt //4
    ? 
    "[{0}]{1}".format_with(choice.Substring(0,1).ToUpperInvariant(), //5
    choice.Substring(1,choice.Length - 1)) 
    :
    choice; //0
    ....
  }
  ....
}

Dalam hal ini, ada logika aneh dari operator ternary. Mari kita melihat lebih dekat: jika kondisi yang ditandai dengan angka 1 terpenuhi, maka kita pergi ke kondisi 2, yang selalu benar , yang berarti baris 3 terpenuhi. Jika kondisi 1 ternyata salah, maka kita pergi ke garis yang ditandai dengan angka 4, kondisi di mana juga selalu benar , yang berarti bahwa baris 5 dijalankan. Dengan demikian, kondisi yang ditandai dengan komentar 0 tidak akan pernah terpenuhi, yang mungkin bukan logika kerja yang diharapkan oleh programmer.

Peringatan N5

Analyzer Warning: V3123[CWE-783] Mungkin Operator '?:' Bekerja dengan cara yang berbeda dari yang diharapkan. Prioritasnya lebih rendah daripada prioritas operator lain dalam kondisinya. Options.cs 1019

private static string GetArgumentName (...., string description)
{
  string[] nameStart;
  if (maxIndex == 1)
  {
    nameStart = new string[]{"{0:", "{"};
  }
  else
  {
    nameStart = new string[]{"{" + index + ":"};
  }
  for (int i = 0; i < nameStart.Length; ++i) 
  {
    int start, j = 0;
    do 
    {
      start = description.IndexOf (nameStart [i], j);
    } 
    while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false);
    ....
    return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
  }
}

Diagnostik bekerja pada satu baris:

while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)

Karena variabel j diinisialisasi ke nol beberapa baris di atas, operator ternary akan mengembalikan false . Karena kondisi ini, loop body hanya akan dieksekusi sekali. Sepertinya saya bahwa potongan kode ini tidak berfungsi sama sekali seperti yang dimaksudkan oleh programmer.

Peringatan N6

Analyzer Warning: V3022 [CWE-571] Ekspresi ' InstallPackageVersions.Count ! = 1' selalu benar. NugetService.cs 1405

private void remove_nuget_cache_for_package(....)
{
  if (!config.AllVersions && installedPackageVersions.Count > 1)
  {
    const string allVersionsChoice = "All versions";
    if (installedPackageVersions.Count != 1)
    {
      choices.Add(allVersionsChoice);
    }
    ....
  }
  ....
}

Inilah kondisi bersarang yang aneh: installPackageVersions.Count! = 1 , yang akan selalu benar . Seringkali, peringatan seperti itu menunjukkan kesalahan logis dalam kode, dan dalam kasus lain, hanya pemeriksaan yang berlebihan.

Peringatan N7

Analyzer Peringatan: V3001 Ada sub-ekspresi identik 'commandArguments.contains ("- apikey")' di sebelah kiri dan di sebelah kanan '||' operator. ArgumentsUtility.cs 42

public static bool arguments_contain_sensitive_information(string
 commandArguments)
{
  return commandArguments.contains("-install-arguments-sensitive")
  || commandArguments.contains("-package-parameters-sensitive")
  || commandArguments.contains("apikey ")
  || commandArguments.contains("config ")
  || commandArguments.contains("push ")
  || commandArguments.contains("-p ")
  || commandArguments.contains("-p=")
  || commandArguments.contains("-password")
  || commandArguments.contains("-cp ")
  || commandArguments.contains("-cp=")
  || commandArguments.contains("-certpassword")
  || commandArguments.contains("-k ")
  || commandArguments.contains("-k=")
  || commandArguments.contains("-key ")
  || commandArguments.contains("-key=")
  || commandArguments.contains("-apikey")
  || commandArguments.contains("-api-key")
  || commandArguments.contains("-apikey")
  || commandArguments.contains("-api-key");
}

Programmer yang menulis kode ini menyalin dua baris terakhir dan lupa mengeditnya. Karena itu, pengguna Chocolatey kehilangan kemampuan untuk menerapkan parameter apikey dalam beberapa cara lagi. Mirip dengan parameter di atas, saya dapat menawarkan opsi seperti:

commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");

Kesalahan salin-rekat memiliki peluang besar cepat atau lambat untuk muncul di proyek apa pun dengan banyak kode sumber, dan salah satu cara terbaik untuk menghadapinya adalah analisis statis.

PS Dan, seperti biasa, kesalahan ini cenderung muncul di akhir kondisi multi-line :). Lihat publikasi " Pengaruh Lini Terakhir ".

Peringatan N8

Analyzer Warning: V3095 [CWE-476] Objek ' InstallPackage ' digunakan sebelum diverifikasi dengan null. Periksa baris: 910, 917. NugetService.cs 910

public virtual ConcurrentDictionary<string, PackageResult> get_outdated(....)
{
  ....
  var pinnedPackageResult = outdatedPackages.GetOrAdd(
    packageName, 
    new PackageResult(installedPackage, 
                      _fileSystem.combine_paths(
                        ApplicationParameters.PackagesLocation, 
                        installedPackage.Id)));
  ....
  if (   installedPackage != null
      && !string.IsNullOrWhiteSpace(installedPackage.Version.SpecialVersion) 
      && !config.UpgradeCommand.ExcludePrerelease)
  {
    ....
  }
  ....
}

Klasik error: pertama, installedPackage objek digunakan, dan kemudian diperiksa untuk nol . Diagnostik ini memberi tahu kita satu dari dua masalah dalam program: salah satu paket yang diinstal tidak pernah nol , yang meragukan, dan kemudian pemeriksaannya berlebihan, atau kita berpotensi mendapatkan kesalahan serius dalam kode - upaya untuk mengakses melalui tautan nol.

Kesimpulan


Jadi kami mengambil langkah kecil lainnya - sekarang menggunakan PVS-Studio menjadi lebih mudah dan nyaman. Saya juga ingin mengatakan bahwa Chocolatey adalah manajer paket yang baik dengan sejumlah kecil kesalahan dalam kode, yang bisa menjadi lebih sedikit ketika menggunakan PVS-Studio.

Kami mengundang Anda untuk mengunduh dan mencoba PVS-Studio. Penggunaan penganalisis statis secara rutin akan meningkatkan kualitas dan keandalan kode yang dikembangkan oleh tim Anda dan membantu mencegah banyak kerentanan zero-day .

PS


Sebelum dipublikasikan, kami mengirim artikel ke pengembang Chocolatey, dan mereka menerimanya dengan baik. Kami tidak menemukan sesuatu yang kritis, tetapi, misalnya, mereka menyukai kesalahan yang kami temukan terkait dengan kunci-api.



Jika Anda ingin berbagi artikel ini dengan audiens yang berbahasa Inggris, silakan gunakan tautan ke terjemahan: Vladislav Stolyarov. PVS-Studio Sudah Hadir dalam Chocolatey: Memeriksa Chocolatey di bawah Azure DevOps .

All Articles