
Vi fortsÀtter att göra anvÀndningen av PVS-Studio enklare. Nu Àr vÄr analysator tillgÀnglig i Chocolatey, en paketförvaltare för Windows. Vi tror att detta kommer att underlÀtta distributionen av PVS-Studio, sÀrskilt i molntjÀnster. För att vara konkreta, lÄt oss kontrollera kÀllkoden för just Chocolatey. Azure DevOps kommer att fungera som CI-system.
HÀr Àr en lista över vÄra andra artiklar om integration med molnsystem:
Jag rekommenderar att du kollar pÄ den första artikeln om integration med Azure DevOps, eftersom vissa punkter har utelÀmnats i detta fall för att undvika duplicering.
SÄ, hjÀltarna i den hÀr artikeln:
â ett verktyg för statisk kodanalys som syftar till att identifiera fel och potentiella sĂ„rbarheter i program skrivna i sprĂ„k som C, C++, C# och Java. Fungerar pĂ„ 64-bitars system pĂ„ Windows, Linux och macOS, och kan analysera kod avsedd för 32-bitars, 64-bitars och inbĂ€ddade ARM-plattformar. Om du provar statisk kodanalys för dina projekt för första gĂ„ngen, rekommenderar vi att du bekantar dig med hur snabbt se de mest intressanta varningarna frĂ„n PVS-Studio och bedöma möjligheterna med detta verktyg.
â en uppsĂ€ttning molntjĂ€nster som tĂ€cker hela utvecklingsprocessen. Plattformen innehĂ„ller verktyg som Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, som alla syftar till att pĂ„skynda utvecklingen av mjukvara och förbĂ€ttra dess kvalitet.
â en paketförvaltare för Windows med öppen kĂ€llkod. Syftet med projektet Ă€r att automatisera hela livscykeln för mjukvara frĂ„n installation till uppdatering och avinstallation i Windows-operativsystem.
Om anvÀndning av Chocolatey
Du kan se hur du installerar sjÀlva paketförvaltaren via den hÀr . FullstÀndig dokumentation för installation av analysatorn finns i avsnittet "Installation med hjÀlp av paketförvaltaren Chocolatey". LÄt mig kort upprepa nÄgra punkter dÀrifrÄn.
Kommandot för att installera den senaste versionen av analysatorn:
choco install pvs-studioKommandot för att installera en specifik version av paketet PVS-Studio:
choco install pvs-studio --version=7.05.35617.2075Som standard installeras endast kĂ€rnan av analyshanteraren - komponenten Core. Alla andra flaggor (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) kan överföras med hjĂ€lp av âpackage-parameters.
Exempel pÄ ett kommando som installerar analyshanteraren med plugin för Visual Studio 2019:
choco install pvs-studio --package-parameters="'\/MSVS2019'"LÄt oss nu titta pÄ ett exempel pÄ hur analyshanteraren anvÀnds bekvÀmt under Azure DevOps.
InstÀllning
Jag pÄminner om att det finns sÀrskilda instruktioner om sÄdana saker som registrering av konto, skapande av Build Pipeline och synkronisering av kontot med projektet som ligger i ett repository pÄ GitHub. . VÄr instÀllning börjar direkt med att skriva en konfigurationsfil.
Först konfigurerar vi en trigger för att ange att vi endast kör kod för förÀndringar i master grenen:
trigger:
- masterDÀrefter behöver vi vÀlja en virtuell maskin. För nÀrvarande kommer detta att vara en Microsoft-hosted agent med Windows Server 2019 och Visual Studio 2019:
pool:
vmImage: 'windows-latest'LÄt oss gÄ vidare till kroppen av konfigurationsfilen (block steps). Trots att vi inte kan installera valfri programvara pÄ den virtuella maskinen har jag inte lagt till en Docker-container. Vi kan lÀgga till Chocolatey som en extension för Azure DevOps. För detta gÄr vi till . Tryck pÄ Get it free. Om du redan Àr inloggad vÀljer du helt enkelt ditt konto, annars gör vi allt samma efter inloggning.

HÀr behöver vi vÀlja var vi ska lÀgga till extensionen och trycka pÄ knappen Installera.

Efter en lyckad installation trycker vi pÄ Proceed to organization:

Nu kan vi se mallen för Chocolatey-uppgiften i fönstret tasks nÀr vi redigerar konfigurationsfilen azure-pipelines.yml:

Klicka pÄ Chocolatey och se en lista med fÀlt:

HÀr behöver vi vÀlja install i fÀltet med kommandon. I Nuspec File Name anger vi namnet pÄ det nödvÀndiga paketet - pvs-studio. Om du inte anger en version installeras den senaste, vilket vi Àr helt okej med. Klicka pÄ knappen add och se det skapade uppdraget i konfigurationsfilen.
steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'LÄt oss gÄ vidare till huvuddelen av vÄr fil:
- task: CmdLine@2
inputs:
script: Nu behöver vi skapa en fil med licensen för analyshanteraren. HÀr PVSNAME och PVSKEY Àr namnen pÄ variablerna vars vÀrden vi anger i instÀllningarna. De kommer att lagra inloggning och licensnyckel för PVS-Studio. För att ange deras vÀrden öppnar vi menyn Variables->New variable. Vi skapar variabler PVSNAME för inloggning och PVSKEY för analysnyckeln. Kom ihÄg att sÀtta en bock HÄll detta vÀrde hemligt för PVSKEY. Kommandokod:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
âu $(PVSNAME) ân $(PVSKEY)Vi samlar in projektet med hjĂ€lp av bat-filen som finns i repot:
call build.batVi skapar en mapp dÀr resultaten frÄn analysatorn kommer att ligga:
call mkdir PVSTestResultsVi startar analysen av projektet:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
ât .srcchocolatey.sln âo .PVSTestResultsChoco.plog Vi konverterar vĂ„r rapport till html-format med hjĂ€lp av verktyget PlogConverter:
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
ât html âo PVSTestResults .PVSTestResultsChoco.plogNu behöver vi skapa en uppgift för att kunna exportera rapporten.
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()Den fullstÀndiga konfigurationsfilen ser ut sÄ hÀr:
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()Klicka Spara->Spara->Kör för att starta uppgiften. Vi exporterar rapporten genom att gÄ till uppgiftstabben.
Projektet Chocolatey innehÄller totalt 37615 rader C#-kod. LÄt oss titta pÄ nÄgra av de funna felen.
Resultat av kontrollen
Varning N1
Analysatorns varning: Variabeln 'Provider' tilldelas sig sjÀlv. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}Analysatorn har upptÀckt att en variabel tilldelas sig sjÀlv, vilket Àr meningslöst. Det Àr troligt att en annan variabel borde stÄ pÄ den platsen. Eller sÄ Àr det ett skrivfel, och den överflödiga tilldelningen kan helt enkelt tas bort.
Varning N2
Analysatorns varning: [CWE-480] Operatorn '&' utvÀrderar bÄda operanderna. Kanske skulle en kortslutande '&&'-operator anvÀndas istÀllet. 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;
}
}Skillnaden mellan operatorn & och operatorn && ligger i att om vĂ€nster del av uttrycket â false, kommer Ă€ndĂ„ den högra sidan att berĂ€knas, vilket i det hĂ€r fallet innebĂ€r onödiga metodanrop system.directory_exists.
I det undersökta fragmentet Àr detta ett litet misstag. Ja, detta villkor kan optimeras genom att byta ut & mot &&, men rent praktiskt pÄverkar det ingenting. Men i andra fall kan förvirringen mellan & och && orsaka allvarliga problem nÀr den högra sidan av uttrycket arbetar med felaktiga/ogiltiga vÀrden. Till exempel, i vÄr samling av fel, , finns det ett sÄdant fall:
if ((k < nct) & (s[k] != 0.0))Ăven om indexet vĂ„gvektor Ă€r felaktigt, kommer det att anvĂ€ndas för att fĂ„ tillgĂ„ng till elementet i arrayen. Som ett resultat kommer ett undantag att genereras IndexOutOfRangeException.
Varningar N3, N4
Analysatorns varning: [CWE-571] Uttrycket 'shortPrompt' Àr alltid sant. InteractivePrompt.cs 101
Analysatorns varning: [CWE-571] Uttrycket 'shortPrompt' Àr alltid sant. 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
....
}
....
}I det hÀr fallet finns det en underlig logik i hur den ternÀra operatorn fungerar. LÄt oss titta nÀrmare: om villkoret mÀrkt med siffra 1 uppfylls, gÄr vi vidare till villkor 2, vilket alltid true, och dÀrför kommer rad 3 att exekveras. Om villkor 1 visar sig vara falskt, gÄr vi istÀllet till raden mÀrkt med siffra 4, dÀr villkoret Àven alltid true, och dÀrför kommer rad 5 att exekveras. DÀrmed kommer villkoren som mÀrkts med kommentar 0 aldrig att exekveras, vilket kanske inte Àr den logik som programmet Àr avsett att följa.
Varning N5
Analysatorns varning: [CWE-783] Kanske fungerar '?:' operatorn pÄ ett annat sÀtt Àn förvÀntat. Dess prioritet Àr lÀgre Àn prioriteten för andra operatorer i sitt villkor. 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 = 0 && j != 0 ? description [j++ - 1] == '{' : false);
....
return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
}
}Diagnostiken aktiverades pÄ raden:
while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)Eftersom variabeln j en flera rader ovan initieras med noll, terneroperatorn kommer att returnera vÀrdet false. PÄ grund av detta kommer kroppens loop att köras endast en gÄng. Jag tror att denna kodfragment fungerar helt annorlunda Àn vad programmeraren avsÄg.
Varning N6
Analysatorns varning: [CWE-571] Uttrycket âinstalledPackageVersions.Count != 1â Ă€r alltid sant. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "Alla versioner";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}HÀr Àr en konstig inre villkor: installedPackageVersions.Count != 1, som alltid kommer att vara true. Ofta indikerar en sÄdan varning en logisk fel i koden, och i andra fall bara en överflödig kontroll.
Varning N7
Analysatorns varning: Det finns identiska deluttryck âcommandArguments.contains("-apikey")â till vĂ€nster och till höger om â||â operatorn. 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");
}Programmeraren som skrev denna kodsnutt kopierade de sista tvÄ raderna och glömde att redigera dem. DÀrför förlorade anvÀndarna av Chocolatey möjligheten att anvÀnda parameter apikey pÄ ett par andra sÀtt. PÄ samma sÀtt som ovanstÄende parametrar kan jag föreslÄ följande alternativ:
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");Copy-paste fel har stor chans att uppstÄ förr eller senare i alla projekt med mycket kÀllkod, och ett av de bÀsta sÀtten att bekÀmpa dem Àr statisk analys.
P.S. Och som alltid tenderar detta fel att dyka upp i slutet av en flerlinesvillkor :). Se publikationen "".
Varning N8
Analysatorns varning: [CWE-476] âinstalledPackageâ objektet anvĂ€ndes innan det verifierades mot null. Kontrollera rader: 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)
{
....
}
....
}Klassiskt fel: objektet anvĂ€nds först installedPackage och kontrolleras sedan för null. Denna diagnos berĂ€ttar för oss om ett av tvĂ„ problem i programmet: antingen installedPackage aldrig Ă€r lika med null, vilket Ă€r tvivelaktigt, och dĂ„ Ă€r kontrollen överflödig, eller sĂ„ kan vi potentiellt fĂ„ ett allvarligt fel i koden â ett försök att fĂ„ tillgĂ„ng via en nullreferens.
Slutsats
Vi har nu gjort ytterligare ett litet steg â att anvĂ€nda PVS-Studio har blivit Ă€nnu enklare och bekvĂ€mare. Jag vill ocksĂ„ sĂ€ga att Chocolatey Ă€r en bra paketmanager med ett fĂ„tal kodfel, som skulle kunna bli Ă€nnu fĂ€rre med anvĂ€ndning av PVS-Studio.
Vi bjuder in och prova PVS-Studio. Regelbundet bruk av en statisk analysator kommer att höja kvaliteten och pÄlitligheten pÄ koden som ditt team utvecklar och hjÀlpa till att förhindra mÄnga .
P.S.
Innan publicering skickade vi artikeln till utvecklarna av Chocolatey, och de tog emot den vÀl. Inga kritiska problem hittades, men de gillade till exempel det fel vi upptÀckte relaterat till nyckeln 'api-key'.
Om du vill dela denna artikel med en engelsktalande publik, vÀnligen anvÀnd lÀnken till översÀttningen: Vladislav Stolyarov. .
KĂ€lla: habr.com
