PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps
Vi fortsätter att göra det bekvämare att använda PVS-Studio. Vår analysator är nu tillgänglig i Chocolatey, en pakethanterare för Windows. Vi tror att detta kommer att underlätta utbyggnaden av PVS-Studio, särskilt i molntjänster. För att inte gå långt, låt oss kolla källkoden för samma Chocolatey. Azure DevOps kommer att fungera som ett CI-system.

Här är en lista över våra andra artiklar om integration med molnsystem:

Jag råder dig att vara uppmärksam på den första artikeln om integration med Azure DevOps, eftersom i det här fallet vissa punkter utelämnas för att inte dupliceras.

Så, hjältarna i denna artikel:

PVS-studio är ett statiskt kodanalysverktyg utformat för att identifiera fel och potentiella sårbarheter i program skrivna i C, C++, C# och Java. Körs på 64-bitars Windows-, Linux- och macOS-system och kan analysera kod designad för 32-bitars, 64-bitars och inbäddade ARM-plattformar. Om det här är första gången du provar statisk kodanalys för att kontrollera dina projekt rekommenderar vi att du bekantar dig med artikel om hur du snabbt kan se de mest intressanta PVS-Studio-varningarna och utvärdera det här verktygets funktioner.

Azure DevOps — en uppsättning molntjänster som gemensamt täcker hela utvecklingsprocessen. Den här plattformen innehåller verktyg som Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, som låter dig påskynda processen att skapa programvara och förbättra dess kvalitet.

Chocolaty är en öppen källkodspakethanterare för Windows. Målet med projektet är att automatisera hela mjukvarans livscykel från installation till uppdatering och avinstallation på Windows operativsystem.

Om att använda Chocolatey

Du kan se hur du installerar själva pakethanteraren här länk. Fullständig dokumentation för installation av analysatorn finns på länk Se avsnittet Installation med Chocolatey Package Manager. Jag ska kort upprepa några punkter därifrån.

Kommando för att installera den senaste versionen av analysatorn:

choco install pvs-studio

Kommando för att installera en specifik version av PVS-Studio-paketet:

choco install pvs-studio --version=7.05.35617.2075

Som standard är bara kärnan i analysatorn, Core-komponenten, installerad. Alla andra flaggor (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) kan skickas med --package-parametrar.

Ett exempel på ett kommando som installerar en analysator med en plugin för Visual Studio 2019:

choco install pvs-studio --package-parameters="'/MSVS2019'"

Låt oss nu titta på ett exempel på bekväm användning av analysatorn under Azure DevOps.

justering

Låt mig påminna dig om att det finns ett separat avsnitt om sådana problem som att registrera ett konto, skapa en Build Pipeline och synkronisera ditt konto med ett projekt som finns i GitHub-förvaret. artikel. Vår installation kommer omedelbart att börja med att skriva en konfigurationsfil.

Låt oss först ställa in en startutlösare, vilket indikerar att vi endast startar för ändringar i Master gren:

trigger:
- master

Därefter måste vi välja en virtuell maskin. För tillfället kommer det att vara en Microsoft-värd agent med Windows Server 2019 och Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Låt oss gå vidare till brödtexten i konfigurationsfilen (block steg). Trots det faktum att du inte kan installera godtycklig programvara i en virtuell maskin, har jag inte lagt till en Docker-behållare. Vi kan lägga till Chocolatey som en förlängning för Azure DevOps. För att göra detta, låt oss gå till länk. Klick Få det gratis. Därefter, om du redan är auktoriserad, välj helt enkelt ditt konto, och om inte, gör sedan samma sak efter auktorisering.

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Här måste du välja var vi ska lägga till tillägget och klicka på knappen installera.

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Efter lyckad installation, klicka Fortsätt till organisation:

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Du kan nu se mallen för Chokladuppgiften i fönstret uppgifter när du redigerar en konfigurationsfil azure-pipelines.yml:

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Klicka på Choklad och se en lista med fält:

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Här måste vi välja installera i fält med lagen. I Nuspec filnamn ange namnet på det önskade paketet – pvs-studio. Om du inte anger version kommer den senaste att installeras, vilket passar oss helt. Låt oss trycka på knappen lägga till och vi kommer att se den genererade uppgiften i konfigurationsfilen.

steps:
- task: ChocolateyCommand@0
  inputs:
    command: 'install'
    installPackageId: 'pvs-studio'

Låt oss sedan gå vidare till huvuddelen av vår fil:

- task: CmdLine@2
  inputs:
    script: 

Nu måste vi skapa en fil med analysatorlicensen. Här PVSNAME и PVSKEY – namn på variabler vars värden vi anger i inställningarna. De kommer att lagra PVS-Studio-inloggningen och licensnyckeln. För att ställa in deras värden, öppna menyn Variabler->Ny variabel. Låt oss skapa variabler PVSNAME för inloggning och PVSKEY för analysatornyckeln. Glöm inte att markera rutan Håll detta värde hemligt för PVSKEY. Kommandokod:

сall "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials 
–u $(PVSNAME) –n $(PVSKEY)

Låt oss bygga projektet med bat-filen som finns i förvaret:

сall build.bat

Låt oss skapa en mapp där filer med resultaten från analysatorn kommer att lagras:

сall mkdir PVSTestResults

Låt oss börja analysera projektet:

сall "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 PlogСonverter-verktyget:

сall "C:Program Files (x86)PVS-StudioPlogConverter.exe" 
–t html –o PVSTestResults .PVSTestResultsChoco.plog

Nu måste du skapa en uppgift så att du kan ladda upp 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()

Låt oss klicka Spara->Spara->Kör att köra uppgiften. Låt oss ladda ner rapporten genom att gå till fliken uppgifter.

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Chocolatey-projektet innehåller endast 37615 rader med C#-kod. Låt oss titta på några av de fel som hittats.

Testresultat

Varning N1

Analysatorvarning: V3005 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 upptäckte en tilldelning av variabeln till sig själv, vilket inte är vettigt. Troligtvis borde det finnas någon annan i stället för en av dessa variabler. Tja, eller så är detta ett stavfel, och den extra uppgiften kan helt enkelt tas bort.

Varning N2

Analysatorvarning: V3093 [CWE-480] Operatören '&' utvärderar båda operanderna. Kanske bör en kortslutnings-&&-operatör 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;
  }
}

Operatörsskillnad & från operatören && är att om vänster sida av uttrycket är falsk, då kommer den högra sidan fortfarande att beräknas, vilket i det här fallet innebär onödiga metodanrop system.directory_exists.

I det betraktade fragmentet är detta ett mindre fel. Ja, detta tillstånd kan optimeras genom att ersätta &-operatören med &&-operatören, men ur praktisk synvinkel påverkar detta ingenting. Men i andra fall kan förväxling mellan & och && orsaka allvarliga problem när den högra sidan av uttrycket behandlas med felaktiga/ogiltiga värden. Till exempel, i vår felsamling, identifieras med V3093-diagnostik, det finns det här fallet:

if ((k < nct) & (s[k] != 0.0))

Även om indexet k är felaktig kommer den att användas för att komma åt ett arrayelement. Som ett resultat kommer ett undantag att kastas IndexOutOfRangeException.

Varningar N3, N4

Analysatorvarning: V3022 [CWE-571] Uttrycket "shortPrompt" är alltid sant. InteractivePrompt.cs 101
Analysatorvarning: V3022 [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 konstig logik bakom driften av den ternära operatören. Låt oss ta en närmare titt: om villkoret jag markerade med nummer 1 är uppfyllt, så går vi vidare till villkor 2, som alltid är sann, vilket betyder att rad 3 kommer att exekveras. Om villkor 1 visar sig vara falskt, kommer vi att gå till raden markerad med nummer 4, villkoret i vilket också alltid är sann, vilket betyder att rad 5 kommer att exekveras. Således kommer villkoren markerade med kommentar 0 aldrig att uppfyllas, vilket kanske inte är exakt den operationslogik som programmeraren förväntade sig.

Varning N5

Analysatorvarning: V3123 [CWE-783] Kanske fungerar '?:'-operatören på ett annat sätt än det förväntades. Dess prioritet är lägre än prioritet för andra operatörer i dess tillstånd. 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);
  }
}

Diagnostiken fungerade för linjen:

while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)

Eftersom variabeln j några rader ovan initieras till noll, kommer den ternära operatorn att returnera värdet falsk. På grund av detta tillstånd kommer slingans kropp endast att exekveras en gång. Det förefaller mig som om den här kodbiten inte alls fungerar som programmeraren tänkt sig.

Varning N6

Analysatorvarning: V3022 [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 = "All versions";
    if (installedPackageVersions.Count != 1)
    {
      choices.Add(allVersionsChoice);
    }
    ....
  }
  ....
}

Det finns ett konstigt kapslat tillstånd här: installedPackageVersions.Count != 1vilket alltid kommer att vara sann. Ofta indikerar en sådan varning ett logiskt fel i koden, och i andra fall indikerar det helt enkelt redundant kontroll.

Varning N7

Analysatorvarning: V3001 Det finns identiska underuttryck 'commandArguments.contains("-apikey")' till vänster och till höger om '||' operatör. 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 den här koden kopierade och klistrade in de två sista raderna och glömde att redigera dem. På grund av detta kunde Chocolatey-användare inte tillämpa parametern apikey ett par sätt till. I likhet med parametrarna ovan kan jag erbjuda följande alternativ:

commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");

Kopiera-klistra-fel har stor chans att dyka upp förr eller senare i alla projekt med en stor mängd källkod, och ett av de bästa verktygen för att bekämpa dem är statisk analys.

PS Och som alltid tenderar detta fel att visas i slutet av ett flerradsvillkor :). Se publikationen "Sista raden effekt".

Varning N8

Analysatorvarning: V3095 [CWE-476] Objektet 'installedPackage' användes innan det verifierades mot null. Kontrollera linjer: 910, 917. NugetService.cs 910

public virtual 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)
  {
    ....
  }
  ....
}

Klassiskt misstag: objekt först installerat paket används och sedan kontrolleras för null. Denna diagnostik berättar om ett av två problem i programmet: antingen installerat paket aldrig lika null, vilket är tveksamt, och då är kontrollen överflödig, eller så kan vi potentiellt få ett allvarligt fel i koden - ett försök att komma åt en nollreferens.

Slutsats

Så vi har tagit ytterligare ett litet steg - nu har det blivit ännu enklare och bekvämare att använda PVS-Studio. Jag skulle också vilja säga att Chocolatey är en bra pakethanterare med ett litet antal fel i koden, som kan vara ännu färre när man använder PVS-Studio.

Vi bjuder in dig hämta och prova PVS-Studio. Regelbunden användning av en statisk analysator kommer att förbättra kvaliteten och tillförlitligheten hos koden som ditt team utvecklar och hjälpa till att förhindra många noll dagars sårbarheter.

PS

Innan publiceringen skickade vi artikeln till Chocolatey-utvecklarna och de tog emot den väl. Vi hittade inget kritiskt, men de, till exempel, gillade buggen vi hittade relaterad till "api-key"-nyckeln.

PVS-Studio är nu i Chocolatey: kollar Chocolatey under Azure DevOps

Om du vill dela den här artikeln med en engelsktalande publik, använd gärna översättningslänken: Vladislav Stolyarov. PVS-Studio är nu i Chocolatey: Checking Chocolatey under Azure DevOps.

Källa: will.com

Lägg en kommentar