Ini adalah artikel kedua, yang berfokus pada penggunaan penganalisa PVS-Studio dalam sistem cloud CI. Kali ini kami akan mempertimbangkan platform Azure DevOps - solusi cloud CI \ CD dari Microsoft. Kami akan menganalisis proyek ShareX.
Kami membutuhkan tiga komponen. Yang pertama adalah analisa PVS-Studio. Yang kedua adalah Azure DevOps, yang akan kami integrasikan dengan analyzer. Yang ketiga adalah proyek yang akan kami periksa untuk menunjukkan kemampuan PVS-Studio saat bekerja di cloud. Jadi ayo pergi.
PVS-Studio adalah penganalisa kode statis untuk menemukan kesalahan dan cacat keamanan. Alat ini mendukung analisis kode C, C ++ dan C #.
Azure DevOps . Platform Azure DevOps mencakup alat-alat seperti Azure Pipeline, Azure Board, Azure Artifacts dan lainnya yang mempercepat proses pembuatan perangkat lunak dan meningkatkan kualitasnya.
ShareX adalah aplikasi gratis yang memungkinkan Anda menangkap dan merekam bagian mana pun dari layar. Proyek ini ditulis dalam C # dan sangat cocok untuk menunjukkan konfigurasi peluncuran analisa statis. Kode sumber proyek
tersedia di GitHub .
Output dari perintah cloc untuk proyek ShareX:
Dengan kata lain, proyek ini kecil, tetapi cukup memadai untuk menunjukkan karya PVS-Studio bersama dengan platform cloud.
Mari kita mulai konfigurasi
Untuk mulai bekerja di Azure DevOps, mari ikuti
tautan dan tekan "Mulai gratis dengan GitHub".
Berikan akses aplikasi Microsoft ke data akun GitHub.
Anda harus membuat akun Microsoft untuk menyelesaikan pendaftaran Anda.
Setelah mendaftar, buat proyek:
Selanjutnya, kita perlu pindah ke "Pipeline" - "Builds" dan membuat pipeline Build baru.
Ketika ditanya di mana kode kami berada, kami akan menjawab - GitHub.
Otorisasi Azure Pipelines dan pilih repositori dengan proyek, yang untuknya kami akan mengkonfigurasi menjalankan penganalisa statis.
Di jendela pemilihan templat, pilih "Starter pipeline."
Kami dapat menjalankan analisis kode statis proyek dengan dua cara: menggunakan agen yang dihosting oleh Microsoft atau di-host sendiri.
Pertama, kami akan menggunakan agen yang dihosting oleh Microsoft. Agen tersebut adalah mesin virtual biasa yang diluncurkan ketika kami menjalankan pipa kami. Mereka dihapus ketika tugas selesai. Penggunaan agen tersebut memungkinkan kami untuk tidak membuang waktu untuk dukungan dan pembaruan mereka, tetapi memberlakukan batasan tertentu, misalnya - ketidakmampuan untuk menginstal perangkat lunak tambahan yang digunakan untuk membangun proyek.
Mari kita ganti konfigurasi default yang disarankan untuk yang berikut untuk menggunakan agen yang dihosting oleh Microsoft:
# Setting up run triggers # Run only for changes in the master branch trigger: - master # Since the installation of random software in virtual machines # is prohibited, we'll use a Docker container, # launched on a virtual machine with Windows Server 1803 pool: vmImage: 'win1803' container: microsoft/dotnet-framework:4.7.2-sdk-windowsservercore-1803 steps: # Download the analyzer distribution - task: PowerShell@2 inputs: targetType: 'inline' script: 'Invoke-WebRequest -Uri https://files.viva64.com/PVS-Studio_setup.exe -OutFile PVS-Studio_setup.exe' - task: CmdLine@2 inputs: workingDirectory: $(System.DefaultWorkingDirectory) script: | # Restore the project and download dependencies nuget restore .\ShareX.sln # Create the directory, where files with analyzer reports will be saved md .\PVSTestResults # Install the analyzer PVS-Studio_setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /COMPONENTS=Core # Create the file with configuration and license information "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials -u $(PVS_USERNAME) -n $(PVS_KEY) # Run the static analyzer and convert the report in html. "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" -t .\ShareX.sln -o .\PVSTestResults\ShareX.plog "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" -t html -o .\PVSTestResults\ .\PVSTestResults\ShareX.plog # Save analyzer reports - task: PublishBuildArtifacts@1 inputs: pathToPublish: PVSTestResults artifactName: PVSTestResults
Catatan: menurut
dokumentasi , wadah yang digunakan harus di-cache dalam gambar mesin virtual, tetapi pada saat penulisan artikel itu tidak berfungsi dan wadah diunduh setiap kali tugas dimulai, yang berdampak negatif pada waktu eksekusi.
Mari kita simpan pipeline dan buat variabel yang akan digunakan untuk membuat file lisensi. Untuk melakukan ini, buka jendela edit pipa dan klik "Variabel" di sudut kanan atas.
Kemudian, tambahkan dua variabel -
PVS_USERNAME dan
PVS_KEY , masing-masing berisi nama pengguna dan kunci lisensi. Saat membuat variabel
PVS_KEY jangan lupa untuk memilih "Rahasiakan nilai ini" untuk mengenkripsi nilai variabel dengan kunci RSA 2048-bit dan untuk menekan output dari nilai variabel dalam log kinerja tugas.
Simpan variabel dan jalankan pipeline dengan mengklik "Run".
Opsi kedua untuk menjalankan analisis - gunakan agen yang di-host-sendiri. Kami dapat menyesuaikan dan mengelola sendiri agen yang dihosting sendiri. Agen tersebut memberikan lebih banyak peluang untuk menginstal perangkat lunak, yang diperlukan untuk membangun dan menguji produk perangkat lunak kami.
Sebelum menggunakan agen tersebut, Anda harus mengonfigurasinya sesuai dengan
instruksi dan menginstal dan
mengkonfigurasi analisa statis.
Untuk menjalankan tugas pada agen yang di-host-sendiri, kami akan mengganti konfigurasi yang disarankan dengan yang berikut:
# Setting up triggers # Run the analysis for master-branch trigger: - master # The task is run on a self-hosted agent from the pool 'MyPool' pool: 'MyPool' steps: - task: CmdLine@2 inputs: workingDirectory: $(System.DefaultWorkingDirectory) script: | # Restore the project and download dependencies nuget restore .\ShareX.sln # Create the directory where files with analyzer reports will be saved md .\PVSTestResults # Run the static analyzer and convert the report in html. "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" -t .\ShareX.sln -o .\PVSTestResults\ShareX.plog "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" -t html -o .\PVSTestResults\ .\PVSTestResults\ShareX.plog # Save analyzer reports - task: PublishBuildArtifacts@1 inputs: pathToPublish: PVSTestResults artifactName: PVSTestResults
Setelah tugas selesai, Anda dapat mengunduh arsip dengan laporan penganalisa di bawah tab "Ringkasan" atau Anda dapat menggunakan ekstensi
Kirim Email yang memungkinkan untuk mengonfigurasi email atau mempertimbangkan alat lain yang nyaman di
Marketplace .
Hasil analisis
Sekarang mari kita lihat beberapa bug yang ditemukan di proyek yang diuji, ShareX.
Pemeriksaan berlebihanUntuk melakukan pemanasan, mari kita mulai dengan kelemahan sederhana dalam kode, yaitu, dengan pemeriksaan berlebihan:
private void PbThumbnail_MouseMove(object sender, MouseEventArgs e) { .... IDataObject dataObject = new DataObject(DataFormats.FileDrop, new string[] { Task.Info.FilePath }); if (dataObject != null) { Program.MainForm.AllowDrop = false; dragBoxFromMouseDown = Rectangle.Empty; pbThumbnail.DoDragDrop(dataObject, DragDropEffects.Copy | DragDropEffects.Move); Program.MainForm.AllowDrop = true; } .... }
Peringatan PVS-Studio: V3022 [CWE-571] Ekspresi 'dataObject! = Null' selalu benar. TaskThumbnailPanel.cs 415
Mari kita perhatikan pemeriksaan variabel
dataObject untuk
null . Kenapa disini?
dataObject tidak boleh
nol dalam kasus ini, karena ini diinisialisasi dengan referensi pada objek yang dibuat. Akibatnya, kami melakukan pemeriksaan berlebihan. Kritis? Tidak. Tampak ringkas? Tidak. Pemeriksaan ini jelas lebih baik dihapus agar tidak mengacaukan kode.
Mari kita lihat fragmen kode lain yang bisa kita komentari dengan cara yang sama:
private static Image GetDIBImage(MemoryStream ms) { .... try { .... return new Bitmap(bmp); .... } finally { if (gcHandle != IntPtr.Zero) { GCHandle.FromIntPtr(gcHandle).Free(); } } .... } private static Image GetImageAlternative() { .... using (MemoryStream ms = dataObject.GetData(format) as MemoryStream) { if (ms != null) { try { Image img = GetDIBImage(ms); if (img != null) { return img; } } catch (Exception e) { DebugHelper.WriteException(e); } } } .... }
Peringatan PVS-Studio: V3022 [CWE-571] Ekspresi 'img! = Null' selalu benar. ClipboardHelpers.cs 289
Dalam metode
GetImageAlternative , variabel
img diperiksa bahwa itu bukan nol tepat setelah instance baru dari kelas
Bitmap dibuat. Perbedaan dari contoh sebelumnya di sini adalah bahwa kita menggunakan metode
GetDIBImage alih-alih konstruktor untuk menginisialisasi variabel
img . Penulis kode menyarankan bahwa pengecualian mungkin terjadi dalam metode ini, tetapi ia menyatakan hanya blok yang
mencoba dan
akhirnya , menghilangkan
tangkapan . Oleh karena itu, jika pengecualian terjadi, metode pemanggil
GetImageAlternative tidak akan mendapatkan referensi ke objek dari tipe
Bitmap , tetapi harus menangani pengecualian di blok
tangkapnya sendiri. Dalam hal ini, variabel
img tidak akan diinisialisasi dan utas eksekusi bahkan tidak akan mencapai
img! = Cek
kosong tetapi akan masuk ke blok tangkap. Akibatnya, penganalisa memang menunjuk ke pemeriksaan yang berlebihan.
Mari kita perhatikan contoh peringatan
V3022 berikut :
private void btnCopyLink_Click(object sender, EventArgs e) { .... if (lvClipboardFormats.SelectedItems.Count == 0) { url = lvClipboardFormats.Items[0].SubItems[1].Text; } else if (lvClipboardFormats.SelectedItems.Count > 0) { url = lvClipboardFormats.SelectedItems[0].SubItems[1].Text; } .... }
Peringatan PVS-Studio: V3022 [CWE-571] Ekspresi 'lvClipboardFormats.SelectedItems.Count> 0' selalu benar. AfterUploadForm.cs 155
Mari kita lihat lebih dekat ekspresi kondisional kedua. Di sana kami memeriksa nilai properti
Hitung baca-saja. Properti ini menunjukkan jumlah elemen dalam instance koleksi
SelectedItems . Kondisi ini hanya dijalankan jika properti
Count lebih besar dari nol. Itu semua akan baik-baik saja, tetapi di eksternal
jika pernyataan
Count sudah diperiksa untuk 0. Contoh koleksi
SelectedItems tidak dapat memiliki jumlah elemen kurang dari nol, oleh karena itu,
Hitungan sama atau lebih besar dari 0. Karena kita sudah sudah melakukan pemeriksaan
Count untuk 0 di pernyataan
if pertama dan itu salah, tidak ada gunanya untuk menulis cek
Count lebih besar dari nol di cabang lain.
Contoh terakhir dari peringatan
V3022 adalah potongan kode berikut:
private void DrawCursorGraphics(Graphics g) { .... int cursorOffsetX = 10, cursorOffsetY = 10, itemGap = 10, itemCount = 0; Size totalSize = Size.Empty; int magnifierPosition = 0; Bitmap magnifier = null; if (Options.ShowMagnifier) { if (itemCount > 0) totalSize.Height += itemGap; .... } .... }
Peringatan PVS-Studio: Ekspresi V3022 'itemCount> 0' selalu salah. RegionCaptureForm.cs 1100
Penganalisis memperhatikan bahwa
itemCount kondisi
> 0 akan selalu salah, karena variabel
itemCount dideklarasikan dan pada saat yang sama ditetapkan nol di atas. Variabel ini tidak digunakan di mana pun hingga kondisi tersebut, oleh karena itu penganalisa benar tentang ekspresi kondisional, yang nilainya selalu salah.
Baiklah, sekarang mari kita lihat sesuatu yang benar-benar ganjil.
Cara terbaik untuk memahami bug adalah memvisualisasikan bugSepertinya kami menemukan kesalahan yang agak menarik di tempat ini:
public static void Pixelate(Bitmap bmp, int pixelSize) { .... float r = 0, g = 0, b = 0, a = 0; float weightedCount = 0; for (int y2 = y; y2 < yLimit; y2++) { for (int x2 = x; x2 < xLimit; x2++) { ColorBgra color = unsafeBitmap.GetPixel(x2, y2); float pixelWeight = color.Alpha / 255; r += color.Red * pixelWeight; g += color.Green * pixelWeight; b += color.Blue * pixelWeight; a += color.Alpha * pixelWeight; weightedCount += pixelWeight; } } .... ColorBgra averageColor = new ColorBgra((byte)(b / weightedCount), (byte)(g / weightedCount), (byte)(r / weightedCount), (byte)(a / pixelCount)); .... }
Saya tidak ingin menunjukkan semua kartu dan mengungkapkan apa yang ditemukan oleh analis kami, jadi mari kita kesampingkan sebentar.
Dengan nama metode, mudah untuk menebak apa yang dilakukannya - Anda memberikannya gambar atau potongan gambar, dan itu menggandakannya. Kode metode ini cukup panjang, jadi kami tidak akan mengutipnya sepenuhnya, tetapi coba jelaskan algoritmanya dan jelaskan bug apa yang berhasil ditemukan oleh PVS-Studio.
Metode ini menerima dua parameter: objek jenis
Bitmap dan nilai tipe
int yang menunjukkan ukuran pikselasi. Algoritma operasi cukup sederhana:
1) Bagi fragmen gambar yang diterima ke dalam kotak dengan sisi sama dengan ukuran pixelation. Misalnya, jika kita memiliki ukuran pixelation sama dengan 15, kita akan mendapatkan kotak, berisi 15x15 = 225 piksel.
2) Selanjutnya, kami melintasi setiap piksel dalam kuadrat ini dan mengakumulasikan nilai bidang
Merah ,
Hijau ,
Biru dan
Alpha dalam variabel perantara, dan sebelum itu gandakan nilai warna yang sesuai dan saluran alfa dengan variabel
pixelWeight , yang diperoleh oleh membagi nilai
Alpha dengan 255 (variabel
Alpha adalah tipe
byte ). Juga ketika melintasi piksel, kami menjumlahkan nilai-nilai, ditulis dalam
pixelWeight ke dalam variabel
WeightedCount . Fragmen kode yang mengeksekusi tindakan di atas adalah sebagai berikut:
ColorBgra color = unsafeBitmap.GetPixel(x2, y2); float pixelWeight = color.Alpha / 255; r += color.Red * pixelWeight; g += color.Green * pixelWeight; b += color.Blue * pixelWeight; a += color.Alpha * pixelWeight; weightedCount += pixelWeight;
Omong-omong, perhatikan bahwa jika nilai variabel
Alpha adalah nol,
pixelWeight tidak akan menambah variabel
WeightedCount nilai apa pun untuk piksel ini. Kami akan membutuhkannya di masa depan.
3) Setelah melintasi semua piksel dalam kuadrat saat ini, kami dapat membuat warna "rata-rata" yang umum untuk kuadrat ini. Kode melakukan ini terlihat sebagai berikut:
ColorBgra averageColor = new ColorBgra((byte)(b / weightedCount), (byte)(g / weightedCount), (byte)(r / weightedCount), (byte)(a / pixelCount));
4) Sekarang ketika kita mendapatkan warna akhir dan menuliskannya dalam variabel
averageColor , kita dapat kembali melintasi setiap piksel persegi dan memberikan nilai dari
averageColor .
5) Kembali ke poin 2 sementara kami memiliki kotak tidak tertangani.
Sekali lagi, variabel
weightedCount tidak sama dengan jumlah semua piksel dalam kuadrat. Misalnya, jika gambar berisi piksel yang benar-benar transparan (nilai nol dalam saluran alfa), variabel
pixelWeight akan menjadi nol untuk piksel ini (
0/255 = 0). Oleh karena itu, piksel ini tidak akan memengaruhi pembentukan variabel
WeightedCount . Ini cukup logis - tidak ada gunanya memperhitungkan warna akun piksel yang benar-benar transparan.
Jadi semuanya masuk akal - pixelation harus bekerja dengan benar. Dan itu benar-benar terjadi. Itu tidak untuk gambar png yang menyertakan piksel dengan nilai di saluran alpha di bawah 255 dan tidak sama dengan nol. Perhatikan gambar pixelated di bawah ini:
Sudahkah Anda melihat pixelation? Kami juga tidak. Oke, sekarang mari kita ungkapkan intrik kecil ini dan jelaskan di mana tepatnya bug itu bersembunyi di metode ini. Kesalahan merayap ke baris perhitungan variabel
pixelWeight :
float pixelWeight = color.Alpha / 255;
Faktanya adalah bahwa ketika mendeklarasikan variabel
pixelWeight sebagai
float , pembuat kode menyiratkan bahwa ketika membagi bidang
Alpha dengan 255, ia akan mendapatkan angka fraksional selain nol dan satu. Di sinilah masalahnya, karena variabel
Alpha adalah tipe
byte . Saat menyelam dengan 255, kami mendapatkan nilai integer. Hanya setelah itu akan secara implisit dilemparkan ke tipe
float , yang berarti bahwa bagian pecahan hilang.
Sangat mudah untuk menjelaskan mengapa tidak mungkin untuk pixelate gambar png dengan transparansi. Karena untuk nilai piksel saluran alpha berada dalam kisaran 0 <Alpha <255, variabel
Alpha dibagi dengan 255 akan selalu menghasilkan 0. Oleh karena itu, nilai variabel
pixelBerat ,
r ,
g ,
b ,
a ,
WeightedCount juga akan selalu menjadi 0. Sebagai hasilnya, rata-rata
Warna kami akan dengan nilai nol di semua saluran: merah - 0, biru - 0, hijau - 0, alfa - 0. Dengan mengecat kotak dalam warna ini, kami tidak mengubah warna asli piksel, karena rata-rata
Warna benar-benar transparan. Untuk memperbaiki kesalahan ini, kita hanya perlu secara eksplisit melemparkan bidang
Alpha ke tipe
float . Versi tetap dari baris kode mungkin terlihat seperti ini:
float pixelWeight = (float)color.Alpha / 255;
Nah, sudah saatnya mengutip pesan PVS-Studio untuk kode yang salah:
Peringatan PVS-Studio: V3041 [CWE-682] Ungkapan itu secara implisit dilemparkan dari tipe 'int' ke tipe 'float'. Pertimbangkan untuk menggunakan pemeran tipe eksplisit untuk menghindari hilangnya bagian fraksional. Contoh: double A = (double) (X) / Y; ImageHelpers.cs 1119
Sebagai perbandingan, mari kita kutip tangkapan layar dari gambar yang benar-benar pixelated, diperoleh pada versi aplikasi yang diperbaiki:
Potensi NullReferenceException public static bool AddMetadata(Image img, int id, string text) { .... pi.Value = bytesText; if (pi != null) { img.SetPropertyItem(pi); return true; } .... }
Peringatan PVS-Studio: V3095 [CWE-476] Objek 'pi' digunakan sebelum diverifikasi terhadap null. Periksa baris: 801, 803. ImageHelpers.cs 801
Fragmen kode ini menunjukkan bahwa penulis berharap bahwa variabel
pi dapat menjadi
nol , itu sebabnya sebelum memanggil metode
SetPropertyItem , centang
pi! = Null terjadi. Sungguh aneh bahwa sebelum pemeriksaan ini properti diberi array byte, karena jika
pi nol , pengecualian dari tipe
NullReferenceException akan dibuang.
Situasi serupa telah terjadi di tempat lain:
private static void Task_TaskCompleted(WorkerTask task) { .... task.KeepImage = false; if (task != null) { if (task.RequestSettingUpdate) { Program.MainForm.UpdateCheckStates(); } .... } .... }
Peringatan PVS-Studio: V3095 [CWE-476] Objek 'tugas' digunakan sebelum diverifikasi terhadap nol. Periksa baris: 268, 270. TaskManager.cs 268
PVS-Studio menemukan kesalahan serupa lainnya. Intinya sama, jadi tidak ada kebutuhan besar untuk mengutip fragmen kode, pesan analisa akan cukup.
Peringatan PVS-Studio: V3095 [CWE-476] Objek 'Config.PhotobucketAccountInfo' digunakan sebelum diverifikasi dengan null. Periksa baris: 216, 219. UploadersConfigForm.cs 216
Nilai pengembalian yang samaFragmen kode yang mencurigakan ditemukan dalam metode
EvalWindows dari kelas
WindowsList , yang mengembalikan
true dalam semua kasus:
public class WindowsList { public List<IntPtr> IgnoreWindows { get; set; } .... public WindowsList() { IgnoreWindows = new List<IntPtr>(); } public WindowsList(IntPtr ignoreWindow) : this() { IgnoreWindows.Add(ignoreWindow); } .... private bool EvalWindows(IntPtr hWnd, IntPtr lParam) { if (IgnoreWindows.Any(window => hWnd == window)) { return true;
Peringatan PVS-Studio: V3009 Aneh bahwa metode ini selalu mengembalikan satu dan nilai 'benar' yang sama. WindowsList.cs 82
Di tampak logis bahwa jika dalam daftar bernama
IgnoreWindows ada pointer dengan nama yang sama dengan
hWnd , metode tersebut harus mengembalikan
false .
Daftar
IgnoreWindows dapat diisi baik ketika memanggil konstruktor
WindowsList (IntPtr ignWindow) atau langsung melalui mengakses properti sebagai milik umum. Lagi pula, menurut Visual Studio, saat ini dalam kode daftar ini tidak diisi. Ini adalah tempat aneh lain dari metode ini.
Panggilan penangan acara yang tidak aman protected void OnNewsLoaded() { if (NewsLoaded != null) { NewsLoaded(this, EventArgs.Empty); } }
Peringatan PVS-Studio: V3083 [CWE-367] Doa yang tidak aman dari acara 'NewsLoaded', NullReferenceException dimungkinkan. Pertimbangkan menugaskan acara ke variabel lokal sebelum menjalankannya. NewsListControl.cs 111
Di sini kasus yang sangat buruk mungkin terjadi. Setelah memeriksa variabel
NewsLoaded untuk null, metode yang menangani acara, dapat berhenti berlangganan, misalnya, di utas lain. Dalam hal ini, pada saat kita masuk ke tubuh pernyataan if, variabel
NewsLoaded akan menjadi nol.
NullReferenceException mungkin terjadi ketika mencoba memanggil pelanggan dari acara
NewsLoaded , yang nol. Jauh lebih aman menggunakan operator bersyarat nol dan menulis ulang kode di atas sebagai berikut:
protected void OnNewsLoaded() { NewsLoaded?.Invoke(this, EventArgs.Empty); }
Alat analisis menunjuk
68 fragmen yang serupa. Kami tidak akan menjelaskan semuanya - mereka semua memiliki pola panggilan yang sama.
Kembalikan null dari ToStringBaru-baru ini saya menemukan dari
artikel yang menarik dari rekan saya bahwa Microsoft tidak merekomendasikan pengembalian nol dari metode
ToString yang ditimpa. PVS-Studio sangat menyadari hal ini:
public override string ToString() { lock (loggerLock) { if (sbMessages != null && sbMessages.Length > 0) { return sbMessages.ToString(); } return null; } }
Peringatan PVS-Studio: V3108 Tidak disarankan untuk mengembalikan 'null' dari metode 'ToSting ()'. Logger.cs 167
Kenapa ditugaskan jika tidak digunakan? public SeafileCheckAccInfoResponse GetAccountInfo() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "account/info/?format=json"); .... }
Peringatan PVS-Studio: V3008 Variabel 'url' diberi nilai dua kali berturut-turut. Mungkin ini sebuah kesalahan. Periksa baris: 197, 196. Seafile.cs 197
Seperti yang dapat kita lihat dari contoh, ketika mendeklarasikan variabel
url , ia diberi nilai, dikembalikan dari metode
FixPrefix . Di baris berikutnya, kami menghapus nilai yang diperoleh bahkan tanpa menggunakannya di mana pun. Kami mendapatkan sesuatu yang mirip dengan kode mati: itu berfungsi, tetapi tidak mempengaruhi hasilnya. Kemungkinan besar, kesalahan ini adalah hasil dari copy-paste, karena fragmen kode tersebut terjadi di 9 metode lainnya. Sebagai contoh, kami akan mengutip dua metode dengan baris pertama yang serupa:
public bool CheckAuthToken() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "auth/ping/?format=json"); .... } .... public bool CheckAPIURL() { string url = URLHelpers.FixPrefix(APIURL); url = URLHelpers.CombineURL(APIURL, "ping/?format=json"); .... }
Kesimpulan
Seperti yang dapat kita lihat, kompleksitas konfigurasi pemeriksaan penganalisis otomatis tidak bergantung pada sistem CI yang dipilih. Kami benar-benar membutuhkan 15 menit dan beberapa klik mouse untuk mengonfigurasi pemeriksaan kode proyek kami dengan penganalisa statis.
Sebagai kesimpulan, kami mengundang Anda untuk
mengunduh dan mencoba penganalisa pada proyek Anda.