
Ne vazhdojmë të bëjmë përdorimin e PVS-Studio më të lehtë. Tani analizuesi ynë është në dispozicion në Chocolatey, menaxherin e paketave për Windows. Mendojmë se kjo do të lehtësojë instalimin e PVS-Studio, veçanërisht në shërbimet cloud. Për të mos u larguar shumë, do të kontrollojmë kodin burimor të Chocolatey. Si sistem CI do të përdorim Azure DevOps.
Ja lista e artikujve tanë të tjerë mbi integrimin me sistemet cloud:
Të rekomandoj të kushtosh vëmendje artikullit të parë mbi integrimin me Azure DevOps, pasi në këtë rast disa pika janë lënë jashtë për të shmangur përsëritjen.
Pra, heronjtë e këtij artikulli janë:
â njĂ« mjet pĂ«r analizĂ«n statike tĂ« kodit, e cila Ă«shtĂ« e destinuar pĂ«r tĂ« identifikuar gabimet dhe potencialet e dobĂ«ta nĂ« programet e shkruara nĂ« gjuhĂ«t C, C++, C# dhe Java. Funksionon nĂ« sisteme 64-bit nĂ« Windows, Linux dhe macOS, dhe mund tĂ« analizojĂ« kodin qĂ« Ă«shtĂ« i destinuar pĂ«r platformat 32-bit, 64-bit dhe ARM tĂ« integruara. NĂ«se je duke provuar analizĂ«n statike tĂ« kodit pĂ«r herĂ« tĂ« parĂ« pĂ«r tĂ« kontrolluar projektet e tua, rekomandojmĂ« tĂ« njohesh me pĂ«r mĂ«nyrĂ«n e shpejtĂ« pĂ«r tĂ« parĂ« paralajmĂ«rimet mĂ« interesante tĂ« PVS-Studio dhe pĂ«r tĂ« vlerĂ«suar mundĂ«sitĂ« e kĂ«tij instrumenti.
â njĂ« grup shĂ«rbimesh cloud qĂ« mbulojnĂ« gjithĂ« procesin e zhvillimit. Ky platformĂ« pĂ«rfshin mjete si Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, qĂ« lejojnĂ« pĂ«rshpejtimin e procesit tĂ« zhvillimit tĂ« softuerit dhe pĂ«rmirĂ«simin e cilĂ«sisĂ« sĂ« tij.
â menaxher paketa pĂ«r Windows me kod tĂ« hapur. QĂ«llimi i projektit Ă«shtĂ« tĂ« automatizojĂ« gjithĂ« ciklin e jetĂ«s sĂ« softuerit, nga instalimi deri te pĂ«rditĂ«simi dhe fshirja nĂ« sistemet operative Windows.
Rreth përdorimit të Chocolatey
Për të parë si të instaloni menaxherin e paketave vetë, mund të ndihmoni në këtë . Dokumentacioni i plotë për instalimin e analizuesit është në dispozicion në në seksionin "Instalimi me përdorimin e menaxherit të paketave Chocolatey". Në përmbledhje, le të përsërisim disa pika nga aty.
Komanda për të instaluar versionin më të fundit të analizuesit:
choco install pvs-studioKomanda për instalimin e një versioni të caktuar të paketës PVS-Studio:
choco install pvs-studio --version=7.05.35617.2075NĂ« mĂ«nyrĂ« tĂ« paracaktuar instalohet vetĂ«m bĂ«rthama e analizuesit â komponenti Core. TĂ« gjithĂ« parametrat e tjerĂ« (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) mund tĂ« kalohen pĂ«rmes âpackage-parameters.
Shembuj komande që do të instalojnë analizuesin me pluginin për Visual Studio 2019:
choco install pvs-studio --package-parameters="'/MSVS2019'"Tani le të shohim një shembull të përdorimit të lehtë të analizuesit nën Azure DevOps.
Konfigurimi
Të kujtojmë se për çështje si regjistrimi i llogarisë, krijimi i Build Pipeline dhe sinkronizimi i llogarisë me projektin në repozitorin në GitHub, ka një të veçantë . Konfigurimi ynë do të fillojë me hartimin e skedës së konfigurimit.
Së pari, le të konfigurojmë trigger-in e nisjes, duke treguar se prodhojmë nisje vetëm për ndryshimet në master degën:
trigger:
- masterMë pas, na nevojitet të zgjedhim makinën virtuale. Aktualisht kjo do të jetë një agjent i hostuar nga Microsoft me Windows Server 2019 dhe Visual Studio 2019:
pool:
vmImage: 'windows-latest'Të kalojmë në trupin e skedës së konfigurimit (bloku steps). Megjithëse në makinën virtuale nuk është e mundur të instalosh softuer të rastësishëm, nuk e kam shtuar një kontejner Docker. Ne mund të shtojmë Chocolatey si një shtesë për Azure DevOps. Për këtë, do të kalojmë te . Klikojmë Get it free. Më pas, nëse jeni tashmë të autorizuar, thjesht zgjidhni llogarinë tuaj, dhe nëse jo, bëni të njëjtën gjë pas autorizimit.

Këtu duhet të zgjidhni se ku do ta shtojmë shtesën dhe të klikoni butonin Instalo.

Pasi ta instaloni me sukses, do të klikoni Proceed to organization:

Tani mund të shihni një model për detyrën e Chocolatey në dritaren detyrat kur po redaktoni skedën e konfigurimit azure-pipelines.yml:

Klikojmë mbi Chocolatey dhe shohim listën e fushave:

KĂ«tu na nevojitet tĂ« zgjedhim install nĂ« fushĂ«n me komandat. NĂ« Nuspec File Name do tĂ« vendosim emrin e paketĂ«s sĂ« nevojshme â pvs-studio. NĂ«se nuk e specifikoni versionin, do tĂ« instalohet versioni mĂ« i fundit, qĂ« na pĂ«rshtatet plotĂ«sisht. KlikojmĂ« mbi butonin shto dhe do tĂ« shohim detyrĂ«n e formuar nĂ« skedĂ«n e konfigurimit.
steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'Më pas kalojmë në pjesën kryesore të skedës sonë:
- task: CmdLine@2
inputs:
script: Tani na nevojitet tĂ« krijojmĂ« njĂ« skedĂ« me licencĂ«n e analizuesit. KĂ«tu PVSNAME dhe PVSKEY â emrat e variablave, vlerat e tĂ« cilave do t'i caktosh nĂ« cilĂ«simet. Ato do tĂ« ruajnĂ« emrin dhe çelĂ«sin e licencĂ«s PVS-Studio. PĂ«r tĂ« caktuar vlerat e tyre, do tĂ« hapim menunĂ« Variables->New variable. Do tĂ« krijojmĂ« variablat PVSNAME pĂ«r emrin e pĂ«rdoruesit dhe PVSKEY pĂ«r çelĂ«sin e analizuesit. Mos harro tĂ« vendosĂ«sh shenjĂ«n Keep this value secret pĂ«r PVSKEY. Kodi i komandĂ«s:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
âu $(PVSNAME) ân $(PVSKEY)Do tĂ« krijojmĂ« projektin me ndihmĂ«n e skedarit bat qĂ« ndodhet nĂ« repository:
call build.batDo të krijojmë një direktori ku do të vendosen skedarët me rezultatet e punës së analizuesit:
call mkdir PVSTestResultsDo të nisim analizën e projektit:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
ât .srcchocolatey.sln âo .PVSTestResultsChoco.plog Do ta konvertojmĂ« raportin tonĂ« nĂ« formatin html me ndihmĂ«n e utilitarit PlogConverter:
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
ât html âo PVSTestResults .PVSTestResultsChoco.plogTani duhet tĂ« krijojmĂ« njĂ« detyrĂ« pĂ«r tĂ« mundĂ«suar eksportimin e raportit.
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()Skedari i plotë i konfigurimit duket kështu:
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-StudioPVS-Studio_Cmd.exe"
credentials âu $(PVSNAME) ân $(PVSKEY)
call build.bat
call mkdir PVSTestResults
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
ât .srcchocolatey.sln âo .PVSTestResultsChoco.plog
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
ât html âo .PVSTestResults .PVSTestResultsChoco.plog
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()Klikoni Ruaj->Ruaj->Ekzekuto për të nisur detyrën. Do të eksportojmë raportin duke hyrë në skedën e detyrave.
Projekti Chocolatey përmban gjithsej 37615 rreshta kodo në C#. Le të shqyrtojmë disa nga gabimet e gjetura.
Rezultatet e kontrollit
Paralajmërimi N1
Kujtesa e analizuesit: Variabla âProviderâ i jepet vetes. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}Analizuesi ka zbuluar një për asignim variablin ndaj vetes, që nuk ka kuptim. Me shumë mundësi, në vend të njërit prej këtyre variablave duhet të jetë ndonjë tjetër. Ose është një gabim shkrimi dhe për asignimin e tepërt mund të eliminohet.
Paralajmërimi N2
Kujtesa e analizuesit: [CWE-480] Operatori â&â vlerĂ«son tĂ« dy operandĂ«t. Ndoshta duhet tĂ« pĂ«rdoret njĂ« operator â&&â pĂ«r shkurtim nĂ« vendin e tij. 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;
}
}Dallimi i operatorit & nga operatori && consiston në atë se nëse ana e majtë e shprehjes është false, do të llogaritet po ashtu ana e djathtë, që në këtë rast nënkupton thirrje të panevojshme të metodës system.directory_exists.
Në fragmentin e shqyrtuar, kjo është një gabim i vogël. Po, kjo kusht mund të optimizohet duke e zëvendësuar operatorin & me operatorin &&, por nga pikëpamja praktike, kjo nuk ndikon në asgjë. Megjithatë, në raste të tjera, ngatërrimi mes & dhe && mund të shkaktojë probleme serioze, kur ana e djathtë e shprehjes punon me vlera të papërshtatshme/jo të lejuara. Për shembull, në koleksionin tonë të gabimeve, , ka një rast të tillë:
if ((k < nct) & (s[k] != 0.0))Edhe nëse indeksi k është i pasaktë, ai do të përdoret për qasje në elementin e array-t. Si pasojë, do të gjenerohet një përjashtim IndexOutOfRangeException.
Paralajmërimet N3, N4
Kujtesa e analizuesit: [CWE-571] Shprehja âshortPromptâ Ă«shtĂ« gjithmonĂ« e vĂ«rtetĂ«. InteractivePrompt.cs 101
Kujtesa e analizuesit: [CWE-571] Shprehja âshortPromptâ Ă«shtĂ« gjithmonĂ« e vĂ«rtetĂ«. 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
....
}
....
}Në këtë rast, ka një logjikë të çuditshme të funksionimit të operatorit ternar. Le të shqyrtojmë më në detaje: nëse kushti i shënuar me numrin 1 përmbushet, atëherë do të kalojmë tek kushti 2, i cili gjithmonë e vërtetë, pra do të përmbushet rreshti 3. Nëse kushti 1 është i fals, atëherë do të kalojmë në rreshtin e shënuar me numrin 4, kushti i të cilit gjithashtu është gjithmonë e vërtetë, pra do të përmbushet rreshti 5. Kështu, kushtet e shënuara me komentarin 0 nuk do të përmbushen kurrë, që mund të përbëjë një logjikë jo aq të saktë për të cilën programuesi ka pasur prirje.
Kujdesi N5
Kujtesa e analizuesit: [CWE-783] Ndoshta operatori â?:â punon nĂ« njĂ« mĂ«nyrĂ« tĂ« ndryshme nga ajo qĂ« ishte pritur. Prioriteti i tij Ă«shtĂ« mĂ« i ulĂ«t se prioriteti i operatorĂ«ve tĂ« tjerĂ« nĂ« kushtin e tij. 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);
}
}Diagnostika ka vepruar në rreshtin:
while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)Duke qenë se variabli j në disa rreshta më sipër është inicializuar në zero, operatori ternar do të kthejë vlerën false. Për shkak të kësaj gjendjeje, trupi i ciklit do të ekzekutohet vetëm një herë. Më duket se ky fragment kodi nuk funksionon ashtu siç e kishte menduar programuesi.
Kujdesi N6
Kujtesa e analizuesit: [CWE-571] Shprehja âinstalledPackageVersions.Count != 1â Ă«shtĂ« gjithmonĂ« e vĂ«rtetĂ«. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "TĂ« gjitha versionet";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}Këtu është një kusht i çuditshëm i përgjakur: installedPackageVersions.Count != 1, i cili gjithmonë do të jetë e vërtetë. Shpesh, një paralajmërim i tillë tregon mbi një gabim logjik në kod, dhe në raste të tjera, thjesht për një kontroll të tepërt.
Paralajmërimi N7
Kujtesa e analizuesit: Ka nĂ«n-shprehje identike âcommandArguments.contains("-apikey")â nĂ« tĂ« majtĂ« dhe nĂ« tĂ« djathtĂ« tĂ« operatorit â||â. 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");
}Programuesi që shkroi këtë pjesë kodi ka kopjuar dy rreshtat e fundit dhe harroi t'i rregullojë ato. Si pasojë, përdoruesit e Chocolatey humbën mundësinë për të aplikuar parametrin apikey me disa mënyra të tjera. Po ashtu, për parametrat e mësipërm, mund të sugjeroj këto variante:
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");Gabimet e kopjim-ngritjes kanë një mundësi të madhe për t'u shfaqur në çdo projekt me një numër të madh kodin burimor, dhe një nga mjetet më të mira për t'u luftuar ato është analiza statike.
P.S. Dhe si gjithmonë, ky gabim ka prirje të shfaqet në fund të një kushti shumë-rreshtor :). Shih publikimin "".
Paralajmërimi N8
Kujtesa e analizuesit: [CWE-476] Objektin âinstalledPackageâ u pĂ«rdor para se tĂ« verifikohej kundrejt null. Kontrolloni rreshtat: 910, 917. NugetService.cs 910
public virtual ConcurrentDictionary 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)
{
....
}
....
}Gabimi klasik: nĂ« fillim objekti installedPackage pĂ«rdoret, dhe mĂ« pas kontrollohet pĂ«r null. Kjo diagnozĂ« na tregon pĂ«r njĂ« nga dy probleme nĂ« program: ose installedPackage nuk Ă«shtĂ« kurrĂ« i barabartĂ« me null, qĂ« Ă«shtĂ« dyshues, dhe atĂ«herĂ« kontrolli Ă«shtĂ« i tepĂ«rt, ose potencialisht mund tĂ« lĂ«shojmĂ« njĂ« gabim tĂ« rĂ«ndĂ« nĂ« kod â njĂ« pĂ«rpjekje pĂ«r qasje pĂ«rmes njĂ« referencĂ« tĂ« null.
Përfundimi
Ja ku e bĂ«mĂ« njĂ« hap tĂ« vogĂ«l tjetĂ«r â tani pĂ«rdorimi i PVS-Studio Ă«shtĂ« bĂ«rĂ« edhe mĂ« i lehtĂ« dhe mĂ« i rehatshĂ«m. Gjithashtu, dua tĂ« them se Chocolatey Ă«shtĂ« njĂ« menaxher i mirĂ« paketash me njĂ« numĂ«r tĂ« vogĂ«l gabimesh nĂ« kodin qĂ« do tĂ« kishte mundur tĂ« ishte edhe mĂ« i vogĂ«l nĂ« pĂ«rdorimin e PVS-Studio.
Ftojme dhe të provoni PVS-Studio. Përdorimi i rregullt i analistit statik do të rrisë cilësinë dhe besueshmërinë e kodit që zhvillohet nga ekipi juaj dhe do të ndihmojë në parandalimin e shumë .
P.S.
Para publikimit, ne e dërguam artikullin zhvilluesve të Chocolatey, dhe ata e pranuan shumë mirë. Nuk gjetëm asgjë kritike, por atyre, për shembull, iu pëlqye gabimi që gjetëm në lidhje me çelësin "api-key".
Nëse dëshironi të ndani këtë artikull me një audiencë anglishtfolëse, ju lutem përdorni lidhjen për përkthimin: Vladislav Stolyarov. .
Burimi: habr.com
