
We blijven het gebruik van PVS-Studio gemakkelijker maken. Nu is onze analyzer beschikbaar in Chocolatey, de pakketbeheerder voor Windows. We geloven dat dit het implementeren van PVS-Studio eenvoudiger zal maken, vooral in cloudservices. Laten we, om niet ver te gaan, de broncode van hetzelfde Chocolatey controleren. Azure DevOps zal als CI-systeem fungeren.
Hier is een lijst van onze andere artikelen over integratie met cloudsystemen:
Ik raad aan om op het eerste artikel over integratie met Azure DevOps te letten, aangezien daarin sommige punten zijn weggelaten om herhaling te voorkomen.
Dus, de helden van dit artikel zijn:
— een tool voor statische code-analyse, bedoeld om fouten en potentiële kwetsbaarheden in programma's geschreven in C, C++, C# en Java te identificeren. Het werkt op 64-bits systemen met Windows, Linux en macOS, en kan code analyseren die bedoeld is voor 32-bits, 64-bits en ingebedde ARM-platforms. Als u voor het eerst statische code-analyse probeert om uw projecten te controleren, raden we aan om kennis te nemen van hoe je snel de meest interessante waarschuwingen van PVS-Studio kunt bekijken en de mogelijkheden van deze tool kunt inschatten.
— een set cloudservices die gezamenlijk het hele ontwikkelingsproces dekken. Deze platform omvat tools zoals Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, die helpen het proces van softwareontwikkeling te versnellen en de kwaliteit ervan te verhogen.
– een open-source pakketbeheerder voor Windows. Het doel van het project is om de gehele levenscyclus van software te automatiseren, van installatie tot update en verwijdering in Windows-besturingssystemen.
Over het gebruik van Chocolatey
Bekijk hoe je de pakketbeheerder zelf kunt installeren via deze . Volledige documentatie over de installatie van de analyzer is beschikbaar via in de sectie 'Installatie met behulp van Chocolatey-pakketbeheerder'. Ik zal kort enkele punten daaruit herhalen.
De opdracht om de nieuwste versie van de analyzer te installeren:
choco install pvs-studioDe opdracht om een specifieke versie van het PVS-Studio-pakket te installeren:
choco install pvs-studio --version=7.05.35617.2075Standaard wordt alleen de kern van de analyzer geïnstalleerd — de Core-component. Alle andere vlaggen (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) kunnen worden doorgegeven met —package-parameters.
Hier is een voorbeeld van een opdracht die de analyzer installeert met de plugin voor Visual Studio 2019:
choco install pvs-studio --package-parameters="'\/MSVS2019'"Laten we nu kijken naar een voorbeeld van het handige gebruik van de analyzer binnen Azure DevOps.
Instellingen
Ik herinner eraan dat er aparte instructies zijn voor zaken zoals het registreren van een account, het aanmaken van een Build Pipeline en het synchroniseren van een account met een project dat in de repository op GitHub staat. . Onze configuratie begint meteen met het schrijven van een configuratiebestand.
Laten we beginnen met het instellen van de activatietrigger door aan te geven dat we alleen starten voor wijzigingen in master de tak:
trigger:
- masterVervolgens moeten we een virtuele machine selecteren. Op dit moment zal dat een Microsoft-hosted agent zijn met Windows Server 2019 en Visual Studio 2019:
pool:
vmImage: 'windows-latest'Laten we naar de inhoud van het configuratiebestand gaan (blok steps). Hoewel er geen willekeurige software op de virtuele machine kan worden geïnstalleerd, heb ik ervoor gekozen om geen Docker-container toe te voegen. We kunnen Chocolatey als uitbreiding voor Azure DevOps toevoegen. Ga hiervoor naar . Klik op Krijg het gratis. Als je al bent ingelogd, kies je gewoon je account; zo niet, doe dan hetzelfde nadat je je hebt aangemeld.

Hier moet je kiezen waar we de uitbreiding willen toevoegen en de knop indrukken Installeren.

Na een succesvolle installatie drukken we op Voortgaan naar organisatie:

Nu kunnen we het sjabloon voor de Chocolatey-taak zien in het venster tasks bij het bewerken van het configuratiebestand azure-pipelines.yml:

Klik op Chocolatey en je ziet een lijst met velden:

Hier moeten we kiezen install in het opdrachtenveld. In Nuspec-bestandsnaam geven we de naam van het gewenste pakket op – pvs-studio. Als we geen versie opgeven, wordt de laatste geïnstalleerd, wat ons volledig tevredenstelt. Klik op de knop add en we zien de gecreëerde taak in het configuratiebestand.
steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'Daarna gaan we naar het belangrijkste deel van ons bestand:
- task: CmdLine@2
inputs:
script: Nu moeten we een bestand met de licentie voor de analyzer aanmaken. Hier PVSNAME en PVSKEY – zijn de namen van de variabelen waarvan we de waarden in de instellingen opgeven. Ze zullen de inloggegevens en de licentiesleutel van PVS-Studio opslaan. Om hun waarden in te stellen, openen we het menu Variabelen-> Nieuwe variabele. We maken variabelen aan PVSNAME voor de inlognaam en PVSKEY voor de analyser sleutel. Vergeet niet het vakje aan te vinken Houd deze waarde geheim voor PVSKEY. Opdrachtcode:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
–u $(PVSNAME) –n $(PVSKEY)Laten we het project bouwen met behulp van het bat-bestand in de repository:
call build.batLaten we een map aanmaken waar de bestanden met de resultaten van de analyser komen te staan:
call mkdir PVSTestResultsLaten we de projectanalyse starten:
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
–t .srcchocolatey.sln –o .PVSTestResultsChoco.plog Laten we ons rapport converteren naar html-formaat met behulp van de PlogConverter-tool:
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
–t html –o PVSTestResults .PVSTestResultsChoco.plogNu moeten we een taak aanmaken zodat we het rapport kunnen exporteren.
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()Het volledige configuratiebestand ziet er als volgt uit:
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()Klik op Opslaan->Opslaan->Uitvoeren voor het starten van de taak. We zullen het rapport exporteren door in het tabblad taken te gaan.
Het Chocolatey-project bevat in totaal 37615 regels C#-code. Laten we enkele van de gevonden fouten bekijken.
Controle resultaten
Waarschuwing N1
Waarschuwing van de analyzer: De 'Provider' variabele verwijst naar zichzelf. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}De analyzer heeft ontdekt dat een variabele aan zichzelf wordt toegewezen, wat geen zin heeft. Waarschijnlijk moet een van deze variabelen iets anders zijn. Of het is een typfout, en de extra toewijzing kan gewoon worden verwijderd.
Waarschuwing N2
Waarschuwing van de analyzer: [CWE-480] De '&' operator evalueert beide operand. Misschien moet in plaats daarvan een kortsluit '&&' operator worden gebruikt. 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;
}
}Het verschil tussen de operator & en de operator && is dat als de linkerzijde van de expressie — false, maar de rechterzijde zal toch worden berekend, wat in dit geval extra aanroepen van de methode inhoudt. system.directory_exists.
In het besproken fragment is dit een klein foutje. Ja, deze voorwaarde kan worden geoptimaliseerd door de operator & vervangen door de operator &&, maar praktisch gezien heeft dit geen invloed. Echter, in andere gevallen kan verwarring tussen & en && ernstige problemen veroorzaken wanneer de rechterzijde van de uitdrukking werkt met onjuiste/onaanvaardbare waarden. Bijvoorbeeld, in onze verzameling fouten, , is er zo'n geval:
if ((k < nct) & (s[k] != 0.0))Zelfs als de index k onjuist is, zal deze worden gebruikt om toegang te krijgen tot het array-element. Dit zal resulteren in een uitzondering IndexOutOfRangeException.
Waarschuwingen N3, N4
Waarschuwing van de analyzer: [CWE-571] Uitdrukking ‘shortPrompt’ is altijd waar. InteractivePrompt.cs 101
Waarschuwing van de analyzer: [CWE-571] Uitdrukking ‘shortPrompt’ is altijd waar. InteractivePrompt.cs 105
public static string
prompt_for_confirmation(.... bool shortPrompt = false, ....)
{
....
if (shortPrompt)
{
var choicePrompt = choice.is_equal_to(defaultChoice) ?
shortPrompt ?
"[[{0}]{1}]".format_with(choice.Substring(0, 1).ToUpperInvariant(),
choice.Substring(1, choice.Length - 1))
:
"[{0}]".format_with(choice.ToUpperInvariant())
:
shortPrompt ?
"[{0}]{1}".format_with(choice.Substring(0,1).ToUpperInvariant(),
choice.Substring(1,choice.Length - 1))
:
choice;
....
}
....
}In dit geval is er een vreemde logica in de werking van de ternary operator. Laten we dit nader bekijken: als de voorwaarde, gemarkeerd met nummer 1, waar is, dan gaan we naar de voorwaarde 2, die altijd true, wat betekent dat regel 3 zal worden uitgevoerd. Als echter voorwaarde 1 vals blijkt te zijn, gaan we naar de regel gemarkeerd met nummer 4, waarvan de voorwaarde ook altijd true, wat betekent dat regel 5 zal worden uitgevoerd. Dus de voorwaarden, gemarkeerd met commentaar 0, zullen nooit worden uitgevoerd, wat misschien niet de logica is waar de programmeur op rekende.
V587
Waarschuwing van de analyzer: [CWE-783] Misschien werkt de ‘?:’ operator anders dan verwacht. De prioriteit is lager dan die van andere operatoren in zijn voorwaarde. 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);
}
}De diagnose werd geactiveerd op regel:
while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false)Aangezien de variabele j En enkele regels hierboven wordt geïnitialiseerd met nul, de ternaire operator retourneert een waarde false. Vanwege deze voorwaarde wordt de lus slechts één keer uitgevoerd. Het lijkt erop dat deze codefragment helemaal niet werkt zoals de programmeur had bedoeld.
Waarschuwing N6
Waarschuwing van de analyzer: [CWE-571] Expressie 'installedPackageVersions.Count != 1' is altijd waar. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "Alle versies";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}Hier is een vreemde geneste voorwaarde: installedPackageVersions.Count != 1, die altijd zal zijn true. Vaak wijst zo'n waarschuwing op een logische fout in de code, en in andere gevallen gewoon op overbodige controle.
Waarschuwing N7
Waarschuwing van de analyzer: Er zijn identieke sub-expressies 'commandArguments.contains("-apikey")' links en rechts van de '||' operator. 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");
}De programmeur die dit codefragment heeft geschreven, heeft de laatste twee regels gekopieerd en vergeten deze te bewerken. Hierdoor hebben gebruikers van Chocolatey de mogelijkheid verloren om de parameter apikey op nog een paar manieren toe te passen. Op dezelfde manier als de bovenstaande parameters, kan ik de volgende opties voorstellen:
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");Copy-paste fouten hebben een grote kans om vroeg of laat op te duiken in elk project met veel broncode, en een van de beste middelen om ze te bestrijden is statische analyse.
P.S. En zoals altijd, heeft deze fout de neiging om aan het einde van een meerlagige voorwaarde op te duiken. Kijk naar de publicatie "".
Waarschuwing N8
Waarschuwing van de analyzer: [CWE-476] Het 'installedPackage' object is gebruikt voordat het tegen null is gecontroleerd. Controleer regels: 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)
{
....
}
....
}Een klassieke fout: eerst wordt het object gebruikt installedPackage en vervolgens gecontroleerd op null. Deze diagnose wijst op een van de twee problemen in de code: ofwel installedPackage is nooit gelijk aan null, wat twijfelachtig is, en dan is de controle overbodig, of we kunnen potentieel een ernstige fout in de code krijgen – een poging om een null-referentie te benaderen.
Conclusie
Hier hebben we weer een kleine stap gezet – het gebruik van PVS-Studio is nu nog eenvoudiger en handiger geworden. Daarnaast wil ik zeggen dat Chocolatey een goede pakketbeheerder is met een klein aantal fouten in de code, wat nog minder zou kunnen zijn met het gebruik van PVS-Studio.
Wij nodigen je uit om PVS-Studio uit te proberen. Het regelmatig gebruik van een statische analyser zal de kwaliteit en de betrouwbaarheid van de code die jouw team ontwikkelt verbeteren en helpen om veel .
P.S.
Voor publicatie hebben we het artikel naar de ontwikkelaars van Chocolatey gestuurd, en zij hebben het goed ontvangen. Er zijn geen kritieke problemen gevonden, maar ze waardeerden bijvoorbeeld de door ons gevonden fout met betrekking tot de "api-key".
Als je dit artikel met een Engelstalig publiek wilt delen, gebruik dan alstublieft de link naar de vertaling: Vladislav Stolyarov. .
Bron: habr.com
