
Folyamatosan azon dolgozunk, hogy a PVS-Studio használata kényelmesebb legyen. Mostantól elemzőnk elérhető a Chocolatey-ban, a Windows csomagkezelőben. Hisszük, hogy ez megkönnyíti a PVS-Studio telepítését, különösen a felhőszolgáltatásokban. Hogy ne menjünk messzire, nézzük meg a Chocolatey forráskódját. Az Azure DevOps fog működni CI rendszerként.
Íme néhány a felhőalapú rendszerekkel való integrációról szóló cikkünkből:
Javaslom, hogy figyelmesen olvassa el az első cikket az Azure DevOps integrációról, mivel ebben az esetben néhány pont kimaradt, hogy ne ismételjük magunkat.
Tehát a cikk főszereplői:
— egy statikus kódelemző eszköz, amely a C, C++, C# és Java nyelveken írt programok hibáinak és potenciális sebezhetőségeinek azonosítására készült. 64-bites rendszereken működik Windows, Linux és macOS alatt, és képes elemezni a 32-bites, 64-bites és beágyazott ARM platformokra szánt kódot. Ha Ön először próbálja ki a kód statikus elemzését projektjei ellenőrzésére, javaslom, hogy ismerkedjen meg a arról, hogyan nézheti meg a PVS-Studio legérdekesebb figyelmeztetéseit gyorsan, és értékelheti az eszköz lehetőségeit.
— a fejlesztési folyamat egészét lefedő felhőszolgáltatások gyűjteménye. E platform tartalmazza az Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos és Azure Test Plans eszközöket, amelyek gyorsítják a szoftverfejlesztési folyamatot és növelik annak minőségét.
– nyílt forráskódú csomagkezelő Windows-ra. A projekt célja az egész szoftver életciklusának automatizálása a telepítéstől a frissítésig és eltávolításig Windows operációs rendszerekben.
A Chocolatey használatáról
Megtekintheti, hogyan telepítse a csomagkezelőt a . A kódelemző telepítéséről részletes dokumentáció érhető el a a „Chocolatey csomagkezelő használatával történő telepítés” részben. Röviden összefoglalom néhány pontját onnan.
A legújabb verziójú elemző telepítési parancsa:
choco install pvs-studioA PVS-Studio adott verziójának telepítési parancsa:
choco install pvs-studio --version=7.05.35617.2075Alapértelmezés szerint csak az elemző alapkomponens, a Core kerül telepítésre. Minden egyéb flag (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) átadható a —package-parameters segítségével.
Példa parancs, amely telepíti az elemzőt a Visual Studio 2019 pluginnal:
choco install pvs-studio --package-parameters="'\/MSVS2019'"Most nézzük meg az elemző kényelmes használatának példáját az Azure DevOps alatt.
Beállítás
Emlékeztetek arra, hogy olyan kérdésekről, mint a fiók regisztrációja, a Build Pipeline létrehozása és a fiók szinkronizálása a GitHubon lévő projekttel, külön . A mi beállításunk közvetlenül a konfigurációs fájl írásával kezdődik.
Először állítsuk be a trigger indítást, megjelölve, hogy változások esetén indítunk csak a következő ágon: master ág:
trigger:
- masterEzután ki kell választanunk a virtuális gépet. Jelenleg ez egy Microsoft-hosted ügynök a Windows Server 2019 és Visual Studio 2019 környezetben:
pool:
vmImage: 'windows-latest'Lépjünk a konfigurációs fájl testére (a blokk steps). Bár a virtuális gépre nem telepíthetünk tetszőleges szoftvert, nem adtam hozzá Docker konténert. A Chocolateyt kiegészítőként tudjuk hozzáadni az Azure DevOps-hoz. Ehhez lépjünk át a . Kattintsunk a Get it free. Ezután, ha már be vagyunk jelentkezve, egyszerűen válasszuk ki a fiókunkat, ha pedig nem, végezzük el ugyanazokat a lépéseket a bejelentkezés után.

Itt ki kell választanunk, hogy hová adjuk hozzá a kiegészítőt, majd nyomjunk a gombra: Telepítés.

A sikeres telepítés után kattintsunk a Proceed to organization:

. Most már láthatjuk a Chocolatey feladat sablonját a tasks konfigurációs fájl szerkesztése közben: azure-pipelines.yml:

Kattintsunk a Chocolateyre, és látni fogjuk a mezők listáját:

Itt ki kell választanunk install a parancsok mezőben. A Nuspec File Name mezőbe beírjuk a szükséges csomag nevét – pvs-studio. Ha nem adjuk meg a verziót, az utolsót telepíti, ami számunkra teljesen megfelelő. Kattintsunk a add gombra, és láthatjuk a konfigurációs fájlban létrejött feladatot.
steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'Ezután lépjünk a fájlunk fő részére:
- task: CmdLine@2
inputs:
script: Most létre kell hoznunk egy fájlt az elemző licencével. Itt PVSNAME és PVSKEY – a változók nevei, amelyek értékeit a beállításokban adjuk meg. Ezek tárolni fogják a PVS-Studio bejelentkezési nevét és licenc kulcsát. Az értékek beállításához nyissuk meg a menüt Variables->New variable. Hozzuk létre a változókat PVSNAME a bejelentkezési névhez és PVSKEY az elemzés kulcsához. Ne felejtsd el bejelölni Tartsd ezt az értéket titokban a PVSKEY. Parancs kód:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
–u $(PVSNAME) –n $(PVSKEY)Összeállítjuk a projektet egy bat fájl segítségével, amely a repóban található:
call build.batHozzunk létre egy mappát, ahol az elemző munkája eredményeként készült fájlok lesznek:
call mkdir PVSTestResultsIndítsuk el a projekt elemzését:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
–t .srcchocolatey.sln –o .PVSTestResultsChoco.plog Konvertáljuk a jelentésünket HTML formátumra a PlogConverter segédprogram használatával:
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
–t html –o PVSTestResults .PVSTestResultsChoco.plogMost létre kell hoznunk egy feladatot, hogy ki tudjuk exportálni a jelentést.
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()A teljes konfigurációs fájl így néz ki:
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()Kattintsunk Save->Save->Run a feladat futtatásához. Az jelentés exportálása a feladat fülre lépve.
A Chocolatey projekt összesen 37615 sor C# kódot tartalmaz. Nézzünk meg néhányat a talált hibák közül.
Ellenőrzés eredményei
1. figyelmeztetés
Elemző figyelmeztetése: A 'Provider' változó önmagához van rendelve. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}Az elemző észlelte, hogy a változó önmagához való hozzárendelése értelmetlen. Valószínűleg az egyik változónak egy másiknak kellene lennie. Vagy elírás, és a felesleges hozzárendelést egyszerűen el lehet távolítani.
2. figyelmeztetés
Elemző figyelmeztetése: [CWE-480] A '&' operátor mindkét operandust kiértékeli. Talán érdemes lenne a rövidzárlatos '&&' operátort használni. 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;
}
}Az operátorok közötti különbség & az operátor && az abban rejlik, hogy ha a kifejezés bal oldala - hamis, akkor a jobb oldalt akkor is ki fogják számítani, ami ebben az esetben felesleges metódushívásokat jelent, system.directory_exists.
A vizsgált részben ez egy apró hiba. Igen, ezt a feltételt optimalizálni lehetne, ha az & operátort && operátorral helyettesítjük, de gyakorlatilag ez semmire sem befolyásolja. Azonban más esetekben az & és && közötti zűrzavar súlyos problémákat okozhat, amikor a kifejezés jobb oldala hibás/érvénytelen értékekkel dolgozik. Például a hibáink gyűjteményében, , van egy ilyen eset:
if ((k < nct) & (s[k] != 0.0))Még akkor is, ha az index k érvénytelen, azt az tömb elemének hozzáférésére fogják használni. Ennek következményeként IndexOutOfRangeException kivétel keletkezik. IndexOutOfRangeException.
Figyelmeztetések N3, N4
Elemző figyelmeztetése: [CWE-571] A ‘shortPrompt’ kifejezés mindig igaz. InteractivePrompt.cs 101
Elemző figyelmeztetése: [CWE-571] A ‘shortPrompt’ kifejezés mindig igaz. InteractivePrompt.cs 105
public static string
prompt_for_confirmation(.... bool shortPrompt = false, ....)
{
....
ha (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
....
}
....
}Ebben az esetben furcsa logika van a ternáris operátor működésében. Vizsgáljuk meg közelebbről: ha a feltétel, amelyet számomra 1-es számmal jelöltem, teljesül, akkor átlépünk a 2-es számmal megjelölt feltételre, amely mindig igaz, ami azt jelenti, hogy a 3-as sor fog végrehajtódni. Ha viszont az 1-es feltétel hamisnak bizonyul, akkor átlépünk a 4-es számmal megjelölt sorra, amelynek feltétele szintén mindig igaz, ami azt jelenti, hogy a 5-ös sor fog végrehajtódni. Így a 0-ás kommmenttel megjelölt feltételek soha nem fognak végrehajtódni, ami lehet, hogy nem azt a logikát jelenti, amire a programozó számított.
Figyelmeztetés N5
Elemző figyelmeztetése: [CWE-783] Talán a ‘?:’ operátor másképp működik, mint várták. Prioritása alacsonyabb, mint a többi operátoré a feltételében. Options.cs 1019
private static string GetArgumentName (...., string description)
{
string[] nameStart;
ha (maxIndex == 1)
{
nameStart = new string[]{"{0:", "{"};
}
egyébként
{
nameStart = new string[]{"{" + index + ":"};
}
for (int i = 0; i = 0 && j != 0 ? description [j++ - 1] == '{' : false);
....
return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
}
}A diagnosztika az alábbi sorra vonatkozott:
while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)Mivel a változó j több sorral feljebb nullával inicializálódik, a ternáris operátor mindig értéket fog visszaadni hamis. Ezen feltétel miatt a ciklus törzse csak egyszer fog végrehajtódni. Úgy gondolom, hogy ez a kódrészlet nem úgy működik, ahogyan a programozó tervezte.
Figyelmeztetés N6
Elemző figyelmeztetése: [CWE-571] Az 'installedPackageVersions.Count != 1' kifejezés mindig igaz. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "Minden verzió";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}Itt furcsa beágyazott feltétel van: installedPackageVersions.Count != 1, ami mindig igaz. Gyakran ilyen figyelmeztetések logikai hibát jeleznek a kódban, más esetekben pedig csak redundáns ellenőrzést mutatnak.
Figyelmeztetés N7
Elemző figyelmeztetése: A ‘commandArguments.contains("-apikey")’ kifejezés bal és jobb oldalán azonos rész-kifejezések találhatók a ‘||’ operátornál. 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");
}A programozó, aki ezt a kódrészt írta, másolta az utolsó két sort, és elfelejtette szerkeszteni őket. Emiatt a Chocolatey felhasználói elvesztették a lehetőséget arra, hogy a apikey paramétert még pár más módon használhassák. Hasonlóan a fenti paraméterekhez, javasolhatok ilyen lehetőségeket:
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");A másolás-beillesztés hibák nagy eséllyel előfordulnak bármely, nagyszámú forráskóddal rendelkező projektben, és az egyik legjobb védekezés ellenük a statikus elemzés.
P.S. Mint mindig, ez a hiba hajlamos a soksoros feltételek végén megjelenni :). Lásd a "".
Figyelmeztetés N8
Elemző figyelmeztetése: [CWE-476] Az 'installedPackage' objektumot a nullával való ellenőrzés előtt használták. Ellenőrizze a 910, 917. sorokat. NugetService.cs 910
nyilvános virtuális 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)
{
....
}
....
}Hagyományos hiba: először az objektumot installedPackage használják, majd utána vizsgálják meg arra, hogy null. Ez a diagnózis arra utal, hogy a programban két probléma állhat fenn: vagy installedPackage soha nincs egyenlő null, ami kétséges, és akkor a vizsgálat felesleges, vagy potenciálisan komoly hibát okozhat a kódban - null referenciára való hivatkozást.
Zárás
Itt egy újabb kis lépést tettünk - most a PVS-Studio használata még egyszerűbb és kényelmesebb lett. Azt is el szeretném mondani, hogy a Chocolatey egy jó csomagkezelő, amelyben kevés hiba van a kódban, amelyek száma még csökkenthető lenne a PVS-Studio használatával.
Meghívjuk és kipróbálni a PVS-Studio-t. A statikus elemző rendszer rendszeres használata növelni fogja a csapatod által fejlesztett kód minőségét és megbízhatóságát, valamint segít megelőzni sok .
P.S.
A közzététel előtt elküldtük a cikket a Chocolatey fejlesztőinek, és ők jól fogadták. Nem találtunk semmi kritikust, de például tetszett nekik a minket érintő hiba, amely az "api-key" kulcshoz kapcsolódott.
Ha szeretnéd megosztani ezt a cikket az angol nyelvű közönséggel, kérlek használd a fordítás linkjét: Vladislav Stolyarov. .
Forrás: habr.com
