PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps
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:

PVS-Studio — 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 artikeln hur snabbt se de mest intressanta varningarna frĂ„n PVS-Studio och bedöma möjligheterna med detta verktyg.

Azure DevOps — 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.

Chocolatey – 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 lÀnken. FullstÀndig dokumentation för installation av analysatorn finns i lÀnken 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-studio

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

choco install pvs-studio --version=7.05.35617.2075

Som 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. artikeln. 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:
- master

DÀ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 lÀnken. 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.

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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.bat

Vi skapar en mapp dÀr resultaten frÄn analysatorn kommer att ligga:

call mkdir PVSTestResults

Vi 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.plog

Nu 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.

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

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: 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 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: V3093 [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, identifierade med hjÀlp av diagnostik V3093, 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: V3022 [CWE-571] Uttrycket 'shortPrompt' Àr alltid sant. InteractivePrompt.cs 101
Analysatorns varning: 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 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: V3123 [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: 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 = "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: V3001 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 "Effekten av den sista raden".

Varning N8

Analysatorns varning: V3095 [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 ladda ner 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 noll-dag sÄrbarheter.

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'.

PVS-Studio finns nu i Chocolatey: kontroll av Chocolatey via Azure DevOps

Om du vill dela denna artikel med en engelsktalande publik, vÀnligen anvÀnd lÀnken till översÀttningen: Vladislav Stolyarov. PVS-Studio Àr nu i Chocolatey: Kontroll av Chocolatey under Azure DevOps.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster