PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps
Ne vazhdojmë ta bëjmë më të përshtatshëm përdorimin e PVS-Studio. Analizatori ynë është tani i disponueshëm në Chocolatey, një menaxher paketash për Windows. Ne besojmë se kjo do të lehtësojë vendosjen e PVS-Studio, në veçanti, në shërbimet cloud. Për të mos shkuar larg, le të kontrollojmë kodin burimor të së njëjtës Chocolatey. Azure DevOps do të veprojë si një sistem CI.

Këtu është një listë e artikujve tanë të tjerë mbi temën e integrimit me sistemet cloud:

Ju këshilloj t'i kushtoni vëmendje artikullit të parë në lidhje me integrimin me Azure DevOps, pasi në këtë rast disa pika hiqen në mënyrë që të mos dublikohen.

Pra, heronjtë e këtij artikulli:

Studio PVS është një mjet i analizës statike të kodit i krijuar për të identifikuar gabimet dhe dobësitë e mundshme në programet e shkruara në C, C++, C# dhe Java. Punon në sistemet 64-bit Windows, Linux dhe macOS dhe mund të analizojë kodin e krijuar për platformat ARM 32-bit, 64-bit dhe të integruar. Nëse kjo është hera juaj e parë që provoni analizën statike të kodit për të kontrolluar projektet tuaja, ju rekomandojmë që të njiheni me të artikull se si të shikoni shpejt paralajmërimet më interesante të PVS-Studio dhe të vlerësoni aftësitë e këtij mjeti.

Azure DevOps — një grup shërbimesh cloud që mbulojnë së bashku të gjithë procesin e zhvillimit. Kjo platformë përfshin mjete të tilla si Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, të cilat ju lejojnë të shpejtoni procesin e krijimit të softuerit dhe të përmirësoni cilësinë e tij.

chocolatey është një menaxher i paketave me burim të hapur për Windows. Qëllimi i projektit është të automatizojë të gjithë ciklin e jetës së softuerit nga instalimi deri te përditësimi dhe çiinstalimi në sistemet operative Windows.

Rreth përdorimit të çokollatës

Këtu mund të shihni se si të instaloni vetë menaxherin e paketave lidhje. Dokumentacioni i plotë për instalimin e analizatorit gjendet në lidhje Shihni seksionin e instalimit duke përdorur menaxherin e paketave Chocolatey. Do të përsëris shkurtimisht disa pika nga atje.

Komanda për të instaluar versionin më të fundit të analizuesit:

choco install pvs-studio

Komanda për të instaluar një version specifik të paketës PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Si parazgjedhje, është instaluar vetëm bërthama e analizuesit, komponenti Core. Të gjithë flamujt e tjerë (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) mund të kalohen duke përdorur parametrat --package.

Një shembull i një komande që do të instalojë një analizues me një shtojcë për Visual Studio 2019:

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

Tani le të shohim një shembull të përdorimit të përshtatshëm të analizuesit nën Azure DevOps.

rregullim

Më lejoni t'ju kujtoj se ekziston një seksion i veçantë për çështje të tilla si regjistrimi i një llogarie, krijimi i një Build Pipeline dhe sinkronizimi i llogarisë tuaj me një projekt të vendosur në depon e GitHub. artikull. Konfigurimi ynë do të fillojë menjëherë me shkrimin e një skedari konfigurimi.

Së pari, le të konfigurojmë një nxitës nisjeje, duke treguar se ne nisemi vetëm për ndryshime në mjeshtër dega:

trigger:
- master

Më pas duhet të zgjedhim një makinë virtuale. Tani për tani do të jetë një agjent i pritur nga Microsoft me Windows Server 2019 dhe Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Le të kalojmë në trupin e skedarit të konfigurimit (bllok Hapat). Përkundër faktit se nuk mund të instaloni softuer arbitrar në një makinë virtuale, unë nuk shtova një kontejner Docker. Mund të shtojmë Chocolatey si një shtesë për Azure DevOps. Për ta bërë këtë, le të shkojmë në lidhje. Klikoni Bëni falas. Më pas, nëse tashmë jeni i autorizuar, thjesht zgjidhni llogarinë tuaj dhe nëse jo, atëherë bëni të njëjtën gjë pas autorizimit.

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Këtu ju duhet të zgjidhni se ku do të shtojmë shtesën dhe klikoni butonin Instaloj.

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Pas instalimit të suksesshëm, klikoni Vazhdoni te organizimi:

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Tani mund të shihni shabllonin për detyrën Chocolatey në dritare detyrat kur redaktoni një skedar konfigurimi azure-pipelines.yml:

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Klikoni në Chocolatey dhe shikoni një listë të fushave:

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Këtu duhet të zgjedhim instaloj në fushë me skuadrat. NË Emri i skedarit Nuspec tregoni emrin e paketës së kërkuar – pvs-studio. Nëse nuk e specifikoni versionin, do të instalohet më i fundit, i cili na përshtatet plotësisht. Le të shtypim butonin shtoj dhe detyrën e krijuar do ta shohim në skedarin e konfigurimit.

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

Më pas, le të kalojmë në pjesën kryesore të skedarit tonë:

- task: CmdLine@2
  inputs:
    script: 

Tani duhet të krijojmë një skedar me licencën e analizuesit. Këtu PVSNAME и PVSKEY – emrat e variablave, vlerat e të cilave ne i specifikojmë në cilësimet. Ata do të ruajnë hyrjen në PVS-Studio dhe çelësin e licencës. Për të vendosur vlerat e tyre, hapni menunë Variabla-> Ndryshore e re. Le të krijojmë variabla PVSNAME për hyrje dhe PVSKEY për çelësin e analizuesit. Mos harroni të kontrolloni kutinë Mbajeni të fshehtë këtë vlerë për PVSKEY. Kodi i komandës:

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

Le të ndërtojmë projektin duke përdorur skedarin bat që ndodhet në depo:

сall build.bat

Le të krijojmë një dosje ku do të ruhen skedarët me rezultatet e analizuesit:

сall mkdir PVSTestResults

Le të fillojmë të analizojmë projektin:

сall "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
–t .srcchocolatey.sln –o .PVSTestResultsChoco.plog 

Ne e konvertojmë raportin tonë në formatin html duke përdorur mjetin PlogСonverter:

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

Tani ju duhet të krijoni një detyrë në mënyrë që të mund të ngarkoni raportin.

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    condition: always()

Skedari i plotë i konfigurimit duket si ky:

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()

Le të klikojmë Save->Save->Run për të ekzekutuar detyrën. Le të shkarkojmë raportin duke shkuar te skeda e detyrave.

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Projekti Chocolatey përmban vetëm 37615 rreshta të kodit C#. Le të shohim disa nga gabimet e gjetura.

Rezultatet e testit

Paralajmërim N1

Paralajmërimi i analizuesit: V3005 Variabla 'Provider' i caktohet vetes. CrytpoHashProviderSpecs.cs 38

public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
  ....
  protected CryptoHashProvider Provider;
  ....
  public override void Context()
  {
    Provider = Provider = new CryptoHashProvider(FileSystem.Object);
  }
}

Analizuesi zbuloi një caktim të ndryshores për veten e tij, gjë që nuk ka kuptim. Me shumë mundësi, në vend të njërit prej këtyre variablave duhet të ketë një tjetër. Epo, ose kjo është një gabim shtypi, dhe detyra shtesë thjesht mund të hiqet.

Paralajmërim N2

Paralajmërimi i analizuesit: V3093 [CWE-480] Operatori '&' vlerëson të dy operandët. Ndoshta në vend të kësaj duhet të përdoret një operator '&&' i qarkut të shkurtër. Platforma.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;
  }
}

Dallimi i operatorit & nga operatori && është se nëse ana e majtë e shprehjes është i rremë, atëherë ende do të llogaritet ana e djathtë, që në këtë rast nënkupton thirrje të panevojshme të metodës sistemi.drejtoria_ekziston.

Në fragmentin e konsideruar, kjo është një e metë e vogël. Po, kjo gjendje mund të optimizohet duke zëvendësuar operatorin & me operatorin &&, por nga pikëpamja praktike, kjo nuk ndikon asgjë. Megjithatë, në raste të tjera, konfuzioni midis & dhe && mund të shkaktojë probleme serioze kur ana e djathtë e shprehjes trajtohet me vlera të pasakta/të pavlefshme. Për shembull, në koleksionin tonë të gabimeve, identifikuar duke përdorur diagnostikimin V3093, ekziston ky rast:

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

Edhe nëse indeksi k është e pasaktë, do të përdoret për të hyrë në një element të grupit. Si rezultat, do të bëhet një përjashtim IndexOutOfRangeException.

Paralajmërimet N3, N4

Paralajmërimi i analizuesit: V3022 [CWE-571] Shprehja 'shortPrompt' është gjithmonë e vërtetë. InteractivePrompt.cs 101
Paralajmërimi i analizuesit: V3022 [CWE-571] Shprehja 'shortPrompt' është gjithmonë e vërtetë. 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
    ....
  }
  ....
}

Në këtë rast, ekziston një logjikë e çuditshme pas funksionimit të operatorit tresh. Le të hedhim një vështrim më të afërt: nëse plotësohet kushti që kam shënuar me numrin 1, atëherë do të kalojmë në kushtin 2, i cili është gjithmonë i vërtetë, që do të thotë se do të ekzekutohet rreshti 3. Nëse kushti 1 rezulton i gabuar, atëherë do të shkojmë në rreshtin e shënuar me numrin 4, kushti në të cilin është gjithashtu gjithmonë i vërtetë, që do të thotë se do të ekzekutohet rreshti 5. Kështu, kushtet e shënuara me komentin 0 nuk do të plotësohen kurrë, gjë që mund të mos jetë saktësisht logjika e funksionimit që priste programuesi.

Paralajmërim N5

Paralajmërimi i analizuesit: V3123 [CWE-783] Ndoshta operatori '?:' funksionon në një mënyrë të ndryshme nga sa pritej. Prioriteti i tij është më i ulët se prioriteti i operatorëve të tjerë në gjendjen e tij. 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);
  }
}

Diagnostifikimi funksionoi për linjën:

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

Që nga ndryshorja j disa rreshta më lart është inicializuar në zero, operatori tresh do të kthejë vlerën i rremë. Për shkak të kësaj gjendjeje, trupi i lakut do të ekzekutohet vetëm një herë. Më duket se kjo pjesë e kodit nuk funksionon fare siç e kishte menduar programuesi.

Paralajmërim N6

Paralajmërimi i analizuesit: V3022 [CWE-571] Shprehja 'installedPackageVersions.Count != 1' është gjithmonë e vërtetë. 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);
    }
    ....
  }
  ....
}

Këtu ka një gjendje të çuditshme të mbivendosur: installedPackageVersions.Count != 1që do të jetë gjithmonë i vërtetë. Shpesh një paralajmërim i tillë tregon një gabim logjik në kod, dhe në raste të tjera thjesht tregon kontroll të tepërt.

Paralajmërim N7

Paralajmërimi i analizuesit: V3001 Ka nën-shprehje identike 'commandArguments.contains("-apikey")' në të majtë dhe në të djathtë të '||' operatori. 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");
}

Programuesi që shkroi këtë pjesë të kodit kopjoi dhe ngjiti dy rreshtat e fundit dhe harroi t'i modifikonte ato. Për shkak të kësaj, përdoruesit e Chocolatey nuk ishin në gjendje të aplikonin parametrin apikey disa mënyra të tjera. Ngjashëm me parametrat e mësipërm, unë mund të ofroj opsionet e mëposhtme:

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

Gabimet e kopjimit dhe ngjitjes kanë një shans të lartë për t'u shfaqur herët a vonë në çdo projekt me një sasi të madhe kodi burimor dhe një nga mjetet më të mira për t'i luftuar ato është analiza statike.

PS Dhe si gjithmonë, ky gabim tenton të shfaqet në fund të një kushti me shumë rreshta :). Shiko botimin "Efekti i linjës së fundit".

Paralajmërim N8

Paralajmërimi i analizuesit: V3095 [CWE-476] Objekti 'installedPackage' u përdor përpara se të verifikohej kundër null. Kontrolloni linjat: 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)
  {
    ....
  }
  ....
}

Gabimi klasik: objekti i parë Paketa e instaluar përdoret dhe më pas kontrollohet për null. Ky diagnostikues na tregon për një nga dy problemet në program: ose Paketa e instaluar kurrë të barabartë null, e cila është e dyshimtë, dhe atëherë kontrolli është i tepërt, ose mund të kemi një gabim serioz në kod - një përpjekje për të hyrë në një referencë nule.

Përfundim

Kështu që ne kemi ndërmarrë një hap tjetër të vogël - tani përdorimi i PVS-Studio është bërë edhe më i lehtë dhe më i përshtatshëm. Do të doja të them gjithashtu se Chocolatey është një menaxher i mirë i paketave me një numër të vogël gabimesh në kod, të cilat mund të jenë edhe më pak kur përdorni PVS-Studio.

Ju ftojmë shkarko dhe provoni PVS-Studio. Përdorimi i rregullt i një analizuesi statik do të përmirësojë cilësinë dhe besueshmërinë e kodit që ekipi juaj zhvillon dhe do të ndihmojë në parandalimin e shumë dobësitë e ditës zero.

PS

Para botimit, ne ia dërguam artikullin zhvilluesve të Chocolatey dhe ata e morën mirë. Ne nuk gjetëm asgjë kritike, por atyre, për shembull, u pëlqeu defekti që gjetëm lidhur me çelësin "api-key".

PVS-Studio është tani në Chocolatey: duke kontrolluar Chocolatey nga nën Azure DevOps

Nëse dëshironi ta ndani këtë artikull me një audiencë anglishtfolëse, ju lutemi përdorni lidhjen e përkthimit: Vladislav Stolyarov. PVS-Studio është tani në Chocolatey: Po kontrollon Chocolatey nën Azure DevOps.

Burimi: www.habr.com

Shto një koment