PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps
Continuăm să facem utilizarea PVS-Studio mai convenabilă. Analizorul nostru este acum disponibil în Chocolatey, un manager de pachete pentru Windows. Credem că acest lucru va facilita implementarea PVS-Studio, în special, în serviciile cloud. Pentru a nu merge departe, să verificăm codul sursă al aceluiași Chocolatey. Azure DevOps va acționa ca un sistem CI.

Iată o listă cu celelalte articole ale noastre pe tema integrării cu sistemele cloud:

Vă sfătuiesc să fiți atenți la primul articol despre integrarea cu Azure DevOps, deoarece în acest caz unele puncte sunt omise pentru a nu fi duplicate.

Deci, eroii acestui articol:

PVS-Studio este un instrument static de analiză a codului conceput pentru a identifica erorile și potențialele vulnerabilități în programele scrise în C, C++, C# și Java. Rulează pe sisteme Windows, Linux și macOS pe 64 de biți și poate analiza codul conceput pentru platformele ARM încorporate pe 32 de biți, 64 de biți și. Dacă este prima dată când încercați analiza codului static pentru a vă verifica proiectele, vă recomandăm să vă familiarizați cu articol despre cum să vizualizați rapid cele mai interesante avertismente PVS-Studio și să evaluați capacitățile acestui instrument.

Azure DevOps — un set de servicii cloud care acoperă împreună întregul proces de dezvoltare. Această platformă include instrumente precum Azure Pipelines, Azure Boards, Azure Artefacts, Azure Repos, Azure Test Plans, care vă permit să accelerați procesul de creare a software-ului și să-i îmbunătățiți calitatea.

Chocolatey este un manager de pachete open source pentru Windows. Scopul proiectului este de a automatiza întregul ciclu de viață al software-ului, de la instalare până la actualizare și dezinstalare pe sistemele de operare Windows.

Despre utilizarea Chocolatey

Puteți vedea cum să instalați managerul de pachete în sine aici legătură. Documentația completă pentru instalarea analizorului este disponibilă la legătură Consultați secțiunea Instalare folosind managerul de pachete Chocolatey. Voi repeta pe scurt câteva puncte de acolo.

Comanda pentru a instala cea mai recentă versiune a analizorului:

choco install pvs-studio

Comanda pentru a instala o versiune specifică a pachetului PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

În mod implicit, este instalat numai miezul analizorului, componenta Core. Toate celelalte indicatoare (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) pot fi transmise folosind --package-parameters.

Un exemplu de comandă care va instala un analizor cu un plugin pentru Visual Studio 2019:

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

Acum să ne uităm la un exemplu de utilizare convenabilă a analizorului în Azure DevOps.

ajustare

Permiteți-mi să vă reamintesc că există o secțiune separată despre probleme precum înregistrarea unui cont, crearea unui Build Pipeline și sincronizarea contului dvs. cu un proiect situat în depozitul GitHub. articol. Configurarea noastră va începe imediat cu scrierea unui fișier de configurare.

Mai întâi, să setăm un declanșator de lansare, indicând că lansăm numai pentru modificări în maestru ramura:

trigger:
- master

În continuare trebuie să selectăm o mașină virtuală. Deocamdată va fi un agent găzduit de Microsoft cu Windows Server 2019 și Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Să trecem la corpul fișierului de configurare (block paşi). În ciuda faptului că nu puteți instala software arbitrar într-o mașină virtuală, nu am adăugat un container Docker. Putem adăuga Chocolatey ca extensie pentru Azure DevOps. Pentru a face acest lucru, să mergem la legătură. Clic Ia-l gratuit. Apoi, dacă sunteți deja autorizat, selectați-vă pur și simplu contul, iar dacă nu, atunci faceți același lucru după autorizare.

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Aici trebuie să selectați unde vom adăuga extensia și să faceți clic pe butonul Instala.

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

După instalarea cu succes, faceți clic Treci la organizare:

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Acum puteți vedea șablonul pentru sarcina Chocolatey în fereastră sarcini la editarea unui fișier de configurare azure-pipelines.yml:

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Faceți clic pe Chocolatey și vedeți o listă de câmpuri:

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Aici trebuie să selectăm instala pe teren cu echipele. ÎN Nuspec fișier indicați numele pachetului solicitat – pvs-studio. Dacă nu specificați versiunea, se va instala cea mai recentă, care ni se potrivește pe deplin. Hai să apăsăm butonul adăuga și vom vedea sarcina generată în fișierul de configurare.

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

În continuare, să trecem la partea principală a fișierului nostru:

- task: CmdLine@2
  inputs:
    script: 

Acum trebuie să creăm un fișier cu licența analizorului. Aici PVSNAME и PVSKEY – numele variabilelor ale căror valori le specificăm în setări. Ei vor stoca login-ul PVS-Studio și cheia de licență. Pentru a le seta valorile, deschideți meniul Variabile->Variabilă nouă. Să creăm variabile PVSNAME pentru autentificare și PVSKEY pentru cheia analizorului. Nu uitați să bifați caseta Păstrați această valoare secretă pentru PVSKEY. Cod de comandă:

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

Să construim proiectul folosind fișierul bat situat în depozit:

сall build.bat

Să creăm un folder în care vor fi stocate fișierele cu rezultatele analizorului:

сall mkdir PVSTestResults

Să începem să analizăm proiectul:

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

Ne convertim raportul în format html folosind utilitarul PlogСonverter:

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

Acum trebuie să creați o sarcină pentru a putea încărca raportul.

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

Fișierul complet de configurare arată astfel:

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

Hai să facem clic Salvare->Salvare->Run pentru a rula sarcina. Să descarcăm raportul accesând fila sarcini.

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Proiectul Chocolatey conține doar 37615 linii de cod C#. Să ne uităm la unele dintre erorile găsite.

Rezultatele testului

Avertisment N1

Avertisment analizor: V3005 Variabila „Furnizor” este atribuită ei însăși. CrytpoHashProviderSpecs.cs 38

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

Analizorul a detectat o atribuire a variabilei către sine, ceea ce nu are sens. Cel mai probabil, în locul uneia dintre aceste variabile ar trebui să existe alta. Ei bine, sau aceasta este o greșeală de tipar și sarcina suplimentară poate fi pur și simplu eliminată.

Avertisment N2

Avertisment analizor: V3093 [CWE-480] Operatorul „&” evaluează ambii operanzi. Poate că în schimb ar trebui folosit un operator de scurtcircuit „&&”. 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;
  }
}

Diferența de operator & de la operator && este că dacă partea stângă a expresiei este fals, atunci partea dreaptă va fi în continuare calculată, ceea ce în acest caz implică apeluri de metodă inutile system.directory_exists.

În fragmentul luat în considerare, acesta este un defect minor. Da, această condiție poate fi optimizată prin înlocuirea operatorului & cu operatorul &&, dar din punct de vedere practic, acest lucru nu afectează nimic. Cu toate acestea, în alte cazuri, confuzia între & și && poate cauza probleme serioase atunci când partea dreaptă a expresiei este tratată cu valori incorecte/invalide. De exemplu, în colecția noastră de erori, identificate folosind diagnosticul V3093, există acest caz:

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

Chiar dacă indicele k este incorectă, va fi folosit pentru a accesa un element de matrice. Ca urmare, va fi aruncată o excepție IndexOutOfRangeException.

Avertismente N3, N4

Avertisment analizor: V3022 [CWE-571] Expresia „shortPrompt” este întotdeauna adevărată. InteractivePrompt.cs 101
Avertisment analizor: V3022 [CWE-571] Expresia „shortPrompt” este întotdeauna adevărată. 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 acest caz, există o logică ciudată în spatele funcționării operatorului ternar. Să aruncăm o privire mai atentă: dacă este îndeplinită condiția pe care am marcat-o cu numărul 1, atunci vom trece la condiția 2, care este întotdeauna adevărat, ceea ce înseamnă că va fi executată linia 3. Dacă condiția 1 se dovedește a fi falsă, atunci vom merge la linia marcată cu numărul 4, condiția în care este de asemenea întotdeauna adevărat, ceea ce înseamnă că se va executa linia 5. Astfel, condițiile marcate cu comentariul 0 nu vor fi niciodată îndeplinite, ceea ce poate să nu fie exact logica de funcționare la care se aștepta programatorul.

Avertisment N5

Avertisment analizor: V3123 [CWE-783] Poate că operatorul „?:” funcționează într-un mod diferit decât era de așteptat. Prioritatea sa este mai mică decât prioritatea altor operatori în starea sa. 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);
  }
}

Diagnosticul a funcționat pentru linie:

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

Din moment ce variabila j câteva linii de mai sus sunt inițializate la zero, operatorul ternar va returna valoarea fals. Din cauza acestei condiții, corpul buclei va fi executat o singură dată. Mi se pare că această bucată de cod nu funcționează deloc așa cum a intenționat programatorul.

Avertisment N6

Avertisment analizor: V3022 [CWE-571] Expresia „installedPackageVersions.Count != 1” este întotdeauna adevărată. 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);
    }
    ....
  }
  ....
}

Există o stare ciudată imbricată aici: installPackageVersions.Count != 1care va fi mereu adevărat. Adesea, un astfel de avertisment indică o eroare logică în cod, iar în alte cazuri indică pur și simplu o verificare redundantă.

Avertisment N7

Avertisment analizor: V3001 Există sub-expresii identice „commandArguments.contains(„-apikey”)’ la stânga și la dreapta lui „||” 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");
}

Programatorul care a scris această secțiune de cod a copiat și lipit ultimele două rânduri și a uitat să le editeze. Din această cauză, utilizatorii Chocolatey nu au putut aplica parametrul apikey încă câteva moduri. Similar cu parametrii de mai sus, pot oferi următoarele opțiuni:

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

Erorile de copiere și inserare au șanse mari să apară mai devreme sau mai târziu în orice proiect cu o cantitate mare de cod sursă, iar unul dintre cele mai bune instrumente pentru a le combate este analiza statică.

PS Și ca întotdeauna, această eroare tinde să apară la sfârșitul unei condiții cu mai multe linii :). Vezi publicația "Efectul de ultimă linie".

Avertisment N8

Avertisment analizor: V3095 [CWE-476] Obiectul „installedPackage” a fost folosit înainte de a fi verificat împotriva null. Verifică linii: 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)
  {
    ....
  }
  ....
}

Greșeală clasică: obiectul mai întâi Pachetul instalat este folosit și apoi verificat zero. Acest diagnostic ne spune despre una dintre cele două probleme din program: fie Pachetul instalat niciodata egali zero, care este îndoielnic, iar apoi verificarea este redundantă sau am putea obține o eroare gravă în cod - o încercare de a accesa o referință nulă.

Concluzie

Așa că am mai făcut un pas mic - acum utilizarea PVS-Studio a devenit și mai ușoară și mai convenabilă. De asemenea, aș dori să spun că Chocolatey este un bun manager de pachete cu un număr mic de erori în cod, care ar putea fi și mai puține atunci când utilizați PVS-Studio.

Te invitam descărca și încercați PVS-Studio. Utilizarea regulată a unui analizor static va îmbunătăți calitatea și fiabilitatea codului dezvoltat de echipa dvs. și va ajuta la prevenirea multor vulnerabilități de zi zero.

PS

Înainte de publicare, am trimis articolul dezvoltatorilor Chocolatey și l-au primit bine. Nu am găsit nimic critic, dar lor, de exemplu, le-a plăcut bug-ul pe care l-am găsit legat de cheia „api-key”.

PVS-Studio este acum în Chocolatey: verifică Chocolatey de sub Azure DevOps

Dacă doriți să împărtășiți acest articol unui public vorbitor de engleză, vă rugăm să folosiți linkul de traducere: Vladislav Stolyarov. PVS-Studio este acum în Chocolatey: se verifică Chocolatey în Azure DevOps.

Sursa: www.habr.com

Adauga un comentariu