
Vi fortsetter Ä gjÞre bruken av PVS-Studio mer praktisk. NÄ er analyseverktÞyet vÄrt tilgjengelig i Chocolatey, en pakkehÄndterer for Windows. Vi mener dette vil lette distribusjonen av PVS-Studio, spesielt i sky-tjenester. For Ä ikke gÄ langt, la oss sjekke kildekoden til nettopp Chocolatey. Som CI-system vil Azure DevOps bli brukt.
Her er en liste over andre artikler om integrasjon med sky-systemer:
Jeg anbefaler Ä se nÊrmere pÄ den fÞrste artikkelen om integrasjon med Azure DevOps, da i dette tilfellet er noen punkter utelatt for ikke Ä duplisere informasjon.
SĂ„, heltene i denne artikkelen:
â et statisk kodeanalyseverktĂžy designet for Ă„ identifisere feil og potensielle sĂ„rbarheter i programmer skrevet i sprĂ„kene C, C++, C# og Java. Det fungerer pĂ„ 64-bits systemer pĂ„ Windows, Linux og macOS, og kan analysere kode beregnet for 32-bits, 64-bits og innebygde ARM-plattformer. Hvis du prĂžver statisk kodeanalyse for fĂžrste gang for Ă„ sjekke prosjektene dine, anbefaler vi Ă„ se nĂŠrmere pĂ„ om hvordan du raskt kan se de mest interessante advarslene fra PVS-Studio og vurdere mulighetene til dette verktĂžyet.
â et sett med sky-tjenester som dekker hele utviklingsprosessen. Plattformen inkluderer verktĂžy som Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, som gjĂžr at programvareutviklingsprosessen kan akselereres og kvaliteten forbedres.
â en pakkehĂ„ndterer for Windows med Ă„pen kildekode. Prosjektets mĂ„l er Ă„ automatisere hele livssyklusen til programvare fra installasjon til oppdatering og fjerning i Windows-operativsystemer.
Om bruken av Chocolatey
Se hvordan du installerer selve pakkehÄndtereren i denne . Den komplette dokumentasjonen for installasjon av analyseverktÞyet er tilgjengelig pÄ i delen «Installasjon med pakkehÄndtereren Chocolatey». La meg kort gjenta noen punkter derfra.
Kommandoen for Ă„ installere den nyeste versjonen av analyseverktĂžyet:
choco install pvs-studioKommandoen for Ă„ installere en spesifikk versjon av PVS-Studio-pakken:
choco install pvs-studio --version=7.05.35617.2075Som standard installeres kun analyzatorens kjerne â komponenten Core. Alle andre flagg (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) kan overfĂžres ved hjelp av âpackage-parameters.
Eksempel pÄ en kommando som installerer analyzatoren med et plugin for Visual Studio 2019:
choco install pvs-studio --package-parameters="'\/MSVS2019'"La oss nÄ se pÄ et eksempel pÄ bruk av analyzatoren under Azure DevOps.
Konfigurasjon
Jeg minner om at for aspekter som registrering av en konto, oppretting av Build Pipeline og synkronisering av kontoen med prosjektet som ligger i GitHub-repositoriet, finnes det et eget . VÄr oppsett vil imidlertid begynne med Ä skrive konfigurasjonsfilen.
FĂžrst vil vi konfigurere utlĂžseren, og angi at vi kun aktiverer for endringer i master grenen:
trigger:
- masterDeretter mÄ vi velge en virtuell maskin. Per nÄ vil dette vÊre en Microsoft-hosted agent med Windows Server 2019 og Visual Studio 2019:
pool:
vmImage: 'windows-latest'La oss gÄ videre til kroppen av konfigurasjonsfilen (blokk steps). Selv om det ikke er mulig Ä installere vilkÄrlig programvare pÄ den virtuelle maskinen, har jeg valgt Ä ikke legge til Docker-containerne. Vi kan legge til Chocolatey som en utvidelse for Azure DevOps. For dette, gÄ til . Klikk pÄ Get it free. Hvis du allerede er logget inn, velger du bare kontoen din, ellers fÞlger du de samme trinnene etter innlogging.

Her mÄ vi velge hvor vi vil legge til utvidelsen og trykke pÄ knappen Installer.

Etter at installeringen er fullfÞrt, klikker vi pÄ Proceed to organization:

NÄ kan vi se malen for Chocolatey-oppgaven i vinduet tasks nÄr vi redigerer konfigurasjonsfilen azure-pipelines.yml:

Klikk pÄ Chocolatey og se listen over felt:

Her mĂ„ vi velge install i feltet med kommandoer. I Nuspec File Name oppgir vi navnet pĂ„ den nĂždvendige pakken â pvs-studio. Hvis vi ikke oppgir versjonen, vil den siste installeres, noe som er helt greit for oss. Klikk pĂ„ knappen add og se oppgaven som er generert i konfigurasjonsfilen.
steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'Deretter gÄr vi til hoveddelen av filen vÄr:
- task: CmdLine@2
inputs:
script: NĂ„ mĂ„ vi opprette en fil med lisensen til analyzatoren. Her PVSNAME og PVSKEY â er navnene pĂ„ variablene, verdiene som vi angir i innstillingen. De vil lagre brukernavnet og lisensnĂžkkelen for PVS-Studio. For Ă„ sette verdiene deres Ă„pner vi menyen Variables->New variable. Vi skal opprette variabler PVSNAME for brukernavnet og PVSKEY for the analyzer key. Don't forget to check the box Hold this value confidential for PVSKEYCommand code:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
âu $(PVSNAME) ân $(PVSKEY)We will compile the project using the bat file located in the repository:
call build.batLet's create a folder where the analyzer's result files will be stored:
call mkdir PVSTestResultsLet's start the project analysis:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
ât .srcchocolatey.sln âo .PVSTestResultsChoco.plog We'll convert our report to html format using the PlogConverter utility:
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
ât html âo PVSTestResults .PVSTestResultsChoco.plogNow we need to create a task to allow the report to be uploaded.
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()The complete configuration file looks like this:
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()Let's press Save->Save->Run to run the task. We will upload the report after accessing the tasks tab.
The Chocolatey project contains a total of 37,615 lines of C# code. Let's look at some of the errors found.
Check results
Advarsel N1
Analyzer warning: The âProviderâ variable is assigned to itself. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}The analyzer detected that a variable was assigned to itself, which makes no sense. Most likely, one of these variables should be some other. Or this is a typo, and the redundant assignment can simply be removed.
Advarsel N2
Analyzer warning: [CWE-480] The â&â operator evaluates both operands. Perhaps a short-circuit â&&â operator should be used instead. 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;
}
}The difference between the operator & and the operator && is that if the left part of the expression â false, so it will still calculate the right part, which in this case implies unnecessary method calls. system.directory_exists.
In the discussed fragment, this is a minor oversight. Yes, this condition can be optimized by replacing the operator & with the operator &&, but from a practical standpoint, it does not affect anything. However, in other cases, the confusion between & and && can lead to serious problems when the right part of the expression operates with incorrect/invalid values. For example, in our collection of errors, , there is such a case:
if ((k < nct) & (s[k] != 0.0))Even if the index k is incorrect, it will be used to access the array element. As a result, an exception will be generated IndexOutOfRangeException.
Warnings N3, N4
Analyzer warning: [CWE-571] Expression âshortPromptâ is always true. InteractivePrompt.cs 101
Analyzer warning: [CWE-571] Expression âshortPromptâ is always true. 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
....
}
....
}In this case, there is a strange logic in how the ternary operator works. Let's consider in more detail: if the condition marked by me with the number 1 is executed, we will move to condition 2, which is always true, which means line 3 will be executed. If condition 1 turns out to be false, we will move to the line marked with number 4, which is also always true, which means line 5 will be executed. Thus, the conditions marked with comment 0 will never be executed, which may not be exactly the logic that the programmer was counting on.
Advarsel N5
Analyzer warning: [CWE-783] Perhaps the â?:â operator works in a different way than it was expected. Its priority is lower than priority of other operators in its condition. 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);
}
}The diagnosis triggered on line:
while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)Since the variable j Tohu kvenn kem dnatikk er i fÀðr? false. Av denne grunnen vil kroppens lÞkke bare kjÞre én gang. Jeg synes denne kodesnutten fungerer helt annerledes enn programmereren hadde tenkt.
Advarsel N6
Analyzer warning: [CWE-571] Uttrykket âinstalledPackageVersions.Count != 1â er alltid sant. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "Alle versjoner";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}Her er det en merkelig nestet betingelse: installedPackageVersions.Count != 1, som alltid vil vĂŠre true. Slik advarsler indikerer ofte en logisk feil i koden, og i andre tilfeller bare en unĂždvendig sjekk.
Advarsel N7
Analyzer warning: Det er identiske sub-uttrykk âcommandArguments.contains("-apikey")â til venstre og til hĂžyre for â||â operatoren. 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");
}Programmereren som skrev denne koden har kopiert de to siste linjene og glemt Ä redigere dem. Som et resultat har brukerne av Chocolatey mistet muligheten til Ä bruke parameteren apikey pÄ flere mÄter. I likhet med parameterne ovenfor, kan jeg foreslÄ fÞlgende alternativer:
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");Copy-paste feil har stor sjanse for Ă„ dukke opp i ethvert prosjekt med mye kildekode, og et av de beste verktĂžyene for Ă„ bekjempe dem er statisk analyse.
P.S. Og som alltid, har denne feilen en tendens til Ä oppstÄ pÄ slutten av en flerlags betingelse :). Se publikasjonen "".
Advarsel N8
Analyzer warning: [CWE-476] âinstalledPackageâ-objektet ble brukt fĂžr det ble verifisert mot null. Sjekk linjer: 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)
{
....
}
....
}Klassisk feil: objektet brukes fĂžrst installedPackage og deretter sjekkes for null. Denne diagnosen forteller oss om et av to problemer i programmet: enten installedPackage aldri er lik null, noe som er tvilsomt, og da er sjekken overflĂždig, eller vi kan potensielt fĂ„ en alvorlig feil i koden â et forsĂžk pĂ„ Ă„ fĂ„ tilgang til nullreferansen.
Konklusjon
Her har vi tatt et lite skritt videre â nĂ„ er det enda enklere og mer praktisk Ă„ bruke PVS-Studio. Jeg vil ogsĂ„ si at Chocolatey er en god pakkebehandler med et lite antall feil i koden, som kunne vĂŠrt enda fĂŠrre med bruk av PVS-Studio.
Vi inviterer og prÞve PVS-Studio. Jevnlig bruk av statisk analyser vil forbedre kvaliteten og pÄliteligheten til koden utviklet av teamet ditt og hjelpe med Ä forhindre mange .
P.S.
FĂžr publisering sendte vi artikkelen til Chocolatey-utviklerne, og de tok imot den godt. Ingenting kritisk ble funnet av oss, men de likte for eksempel feilen vi fant, knyttet til nĂžkkelen "api-key".
Hvis du vil dele denne artikkelen med et engelsksprÄklig publikum, vennligst bruk linken til oversettelsen: Vladislav Stolyarov. .
Kilde: habr.com
