„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“
Ir toliau darome PVS-Studio naudojimą patogesnį. Mūsų analizatorius dabar pasiekiamas Chocolatey, paketų tvarkyklėje, skirtoje Windows. Manome, kad tai palengvins PVS-Studio diegimą, ypač debesijos paslaugose. Kad toli nenueitų, patikrinkime to paties Chocolatey šaltinio kodą. Azure DevOps veiks kaip CI sistema.

Čia yra kitų mūsų straipsnių integracijos su debesų sistemomis tema sąrašas:

Patariu atkreipti dėmesį į pirmąjį straipsnį apie integraciją su Azure DevOps, nes šiuo atveju kai kurie punktai praleidžiami, kad nebūtų dubliuojami.

Taigi, šio straipsnio herojai:

„PVS-Studio“ yra statinio kodo analizės įrankis, skirtas C, C++, C# ir Java kalbomis parašytų programų klaidoms ir galimiems pažeidžiamumui nustatyti. Veikia 64 bitų Windows, Linux ir macOS sistemose ir gali analizuoti kodą, sukurtą 32 bitų, 64 bitų ir įterptoms ARM platformoms. Jei tai pirmas kartas, kai bandote statinę kodo analizę, kad patikrintumėte savo projektus, rekomenduojame su ja susipažinti straipsnis apie tai, kaip greitai peržiūrėti įdomiausius PVS-Studio įspėjimus ir įvertinti šio įrankio galimybes.

„Azure DevOps“ — debesijos paslaugų rinkinys, kuris kartu apima visą kūrimo procesą. Ši platforma apima tokius įrankius kaip Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, kurie leidžia pagreitinti programinės įrangos kūrimo procesą ir pagerinti jos kokybę.

Chocolatey yra atvirojo kodo paketų tvarkyklė, skirta „Windows“. Projekto tikslas – automatizuoti visą programinės įrangos gyvavimo ciklą nuo įdiegimo iki atnaujinimo ir pašalinimo Windows operacinėse sistemose.

Apie Chocolatey naudojimą

Čia galite pamatyti, kaip įdiegti pačią paketų tvarkyklę nuoroda. Visą analizatoriaus montavimo dokumentaciją rasite adresu nuoroda Žr. skyrių Diegimas naudojant „Chocolatey“ paketų tvarkyklę. Iš ten trumpai pakartosiu kai kuriuos punktus.

Komanda įdiegti naujausią analizatoriaus versiją:

choco install pvs-studio

Komanda įdiegti konkrečią PVS-Studio paketo versiją:

choco install pvs-studio --version=7.05.35617.2075

Pagal numatytuosius nustatymus įdiegta tik analizatoriaus šerdis, Core komponentas. Visos kitos vėliavėlės (atskira, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) gali būti perduodamos naudojant --package-parameters.

Komandos, kuri įdiegs analizatorių su „Visual Studio 2019“ papildiniu, pavyzdys:

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

Dabar pažvelkime į patogaus „Azure DevOps“ analizatoriaus naudojimo pavyzdį.

reguliavimas

Leiskite jums priminti, kad yra atskiras skyrius apie tokias problemas kaip paskyros registravimas, „Build Pipeline“ kūrimas ir paskyros sinchronizavimas su projektu, esančiu „GitHub“ saugykloje. straipsnis. Mūsų sąranka iškart prasidės rašant konfigūracijos failą.

Pirmiausia nustatykime paleidimo aktyviklį, nurodantį, kad paleidžiame tik pasikeitus meistras filialas:

trigger:
- master

Toliau turime pasirinkti virtualią mašiną. Kol kas tai bus „Microsoft“ priglobtas agentas su „Windows Server 2019“ ir „Visual Studio 2019“:

pool:
  vmImage: 'windows-latest'

Pereikime prie konfigūracijos failo turinio (blokuoti žingsniai). Nepaisant to, kad negalite įdiegti savavališkos programinės įrangos į virtualią mašiną, aš nepridėjau „Docker“ konteinerio. Galime pridėti „Chocolatey“ kaip „Azure DevOps“ plėtinį. Norėdami tai padaryti, eikime į nuoroda. Spustelėkite Gaukite nemokamai. Tada, jei jau esate įgaliotas, tiesiog pasirinkite savo paskyrą, o jei ne, atlikite tą patį po autorizacijos.

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Čia turite pasirinkti, kur pridėsime plėtinį, ir spustelėkite mygtuką įrengti.

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Sėkmingai įdiegę spustelėkite Pereikite prie organizacijos:

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Dabar lange galite pamatyti Chocolatey užduoties šabloną užduotys kai redaguojate konfigūracijos failą azure-pipelines.yml:

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Spustelėkite Chocolatey ir pamatysite laukų sąrašą:

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Čia turime pasirinkti įrengti aikštėje su komandomis. IN Nuspec failo pavadinimas nurodykite reikiamo paketo pavadinimą – pvs-studio. Jei nenurodysite versijos, bus įdiegta naujausia, kuri mums visiškai tinka. Paspauskite mygtuką add ir sugeneruotą užduotį pamatysime konfigūracijos faile.

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

Toliau pereikime prie pagrindinės failo dalies:

- task: CmdLine@2
  inputs:
    script: 

Dabar turime sukurti failą su analizatoriaus licencija. Čia PVSNAME и PVSKEY – kintamųjų, kurių reikšmes nurodome nustatymuose, pavadinimai. Jie išsaugos PVS-Studio prisijungimo vardą ir licencijos raktą. Norėdami nustatyti jų reikšmes, atidarykite meniu Kintamieji->Naujas kintamasis. Sukurkime kintamuosius PVSNAME prisijungimui ir PVSKEY analizatoriaus raktui. Nepamirškite pažymėti langelio Laikykite šią vertę paslaptyje PVSKEY. Komandos kodas:

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

Sukurkime projektą naudodami saugykloje esantį bat failą:

сall build.bat

Sukurkime aplanką, kuriame bus saugomi failai su analizatoriaus rezultatais:

сall mkdir PVSTestResults

Pradėkime analizuoti projektą:

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

Ataskaitą konvertuojame į html formatą naudodami PlogСonverter įrankį:

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

Dabar turite sukurti užduotį, kad galėtumėte įkelti ataskaitą.

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

Visas konfigūracijos failas atrodo taip:

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

Spauskime Išsaugoti->Išsaugoti->Vykdyti vykdyti užduotį. Atsisiųskite ataskaitą eidami į užduočių skirtuką.

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

„Chocolatey“ projekte yra tik 37615 C# kodo eilučių. Pažvelkime į kai kurias rastas klaidas.

Testo rezultatai

Įspėjimas N1

Analizatoriaus įspėjimas: V3005 Kintamasis „Teikėjas“ priskiriamas jam pačiam. CrytpoHashProviderSpecs.cs 38

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

Analizatorius aptiko kintamojo priskyrimą sau, o tai nėra prasminga. Greičiausiai vietoj vieno iš šių kintamųjų turėtų būti kitas. Na, arba tai yra rašybos klaida, ir papildomą užduotį galima tiesiog pašalinti.

Įspėjimas N2

Analizatoriaus įspėjimas: V3093 [CWE-480] Operatorius „&“ įvertina abu operandus. Galbūt vietoj to reikėtų naudoti trumpojo jungimo „&&“ operatorių. 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;
  }
}

Operatoriaus skirtumas & iš operatoriaus && yra tai, kad jei kairioji išraiškos pusė yra klaidingas, tada vis tiek bus skaičiuojama dešinė pusė, o tai šiuo atveju reiškia nereikalingus metodų iškvietimus system.directory_exists.

Nagrinėtame fragmente tai yra nedidelis trūkumas. Taip, šią sąlygą galima optimizuoti pakeitus operatorių & operatoriumi &&, tačiau praktiniu požiūriu tai nieko nedaro. Tačiau kitais atvejais & ir && supainiojimas gali sukelti rimtų problemų, kai dešinėje išraiškos pusėje pateikiamos neteisingos / netinkamos reikšmės. Pavyzdžiui, mūsų klaidų rinkinyje nustatyta naudojant V3093 diagnostiką, yra toks atvejis:

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

Net jei indeksas k yra neteisingas, jis bus naudojamas norint pasiekti masyvo elementą. Dėl to bus padaryta išimtis IndexOutOfRangeException.

Įspėjimai N3, N4

Analizatoriaus įspėjimas: V3022 [CWE-571] Išraiška „shortPrompt“ visada teisinga. InteractivePrompt.cs 101
Analizatoriaus įspėjimas: V3022 [CWE-571] Išraiška „shortPrompt“ visada teisinga. 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
    ....
  }
  ....
}

Šiuo atveju už trijų dalių operatoriaus veikimo slypi keista logika. Pažiūrėkime atidžiau: jei bus įvykdyta sąlyga, kurią pažymėjau skaičiumi 1, tada pereisime prie 2 sąlygos, kuri visada yra tiesa, o tai reiškia, kad bus vykdoma 3 eilutė. tiesa, o tai reiškia, kad bus vykdoma eilutė 5. Taigi sąlygos, pažymėtos komentaru 0, niekada nebus įvykdytos, o tai gali būti ne visai tokia veikimo logika, kokios tikėjosi programuotojas.

Įspėjimas N5

Analizatoriaus įspėjimas: V3123 [CWE-783] Galbūt operatorius „?:“ veikia kitaip, nei buvo tikėtasi. Jo prioritetas yra mažesnis nei kitų operatorių prioritetas pagal savo būklę. 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);
  }
}

Diagnostika pavyko šiai linijai:

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

Kadangi kintamasis j kelios eilutės aukščiau yra inicijuojamos į nulį, trijų dalių operatorius grąžins reikšmę klaidingas. Dėl šios sąlygos kilpos korpusas bus vykdomas tik vieną kartą. Man atrodo, kad ši kodo dalis neveikia taip, kaip programuotojas norėjo.

Įspėjimas N6

Analizatoriaus įspėjimas: V3022 [CWE-571] Išraiška „installedPackageVersions.Count != 1“ visada teisinga. 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);
    }
    ....
  }
  ....
}

Čia yra keista įdėta sąlyga: installPackageVersions.Count != 1kuri visada bus tiesa. Dažnai toks įspėjimas rodo loginę kodo klaidą, o kitais atvejais tiesiog nurodo perteklinį tikrinimą.

Įspėjimas N7

Analizatoriaus įspėjimas: V3001 Kairėje ir dešinėje nuo „||“ yra identiški antriniai reiškiniai „commandArguments.contains("-apikey")' operatorius. 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");
}

Programuotojas, parašęs šią kodo dalį, nukopijavo ir įklijavo paskutines dvi eilutes ir pamiršo jas redaguoti. Dėl šios priežasties Chocolatey vartotojai negalėjo pritaikyti parametro apikey dar pora būdų. Panašiai kaip ir aukščiau pateikti parametrai, galiu pasiūlyti šias parinktis:

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

Didelė tikimybė, kad kopijavimo ir įklijavimo klaidos anksčiau ar vėliau atsiras bet kuriame projekte, kuriame yra daug šaltinio kodo, o viena geriausių priemonių su jomis kovoti yra statinė analizė.

PS Ir kaip visada, ši klaida dažniausiai atsiranda kelių eilučių sąlygos pabaigoje :). Žiūrėti leidinį "Paskutinės eilutės efektas".

Įspėjimas N8

Analizatoriaus įspėjimas: V3095 [CWE-476] Objektas „installedPackage“ buvo naudojamas prieš patikrinant, ar jis yra nulinis. Patikrinimo eilutės: 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)
  {
    ....
  }
  ....
}

Klasikinė klaida: objektas pirmas įdiegtasPaketas yra naudojamas ir tada patikrinamas null. Ši diagnostika praneša apie vieną iš dviejų programos problemų: arba įdiegtasPaketas niekada nelygus null, kuris yra abejotinas, o tada patikrinimas yra perteklinis, arba galbūt galime gauti rimtą kodo klaidą – bandymą pasiekti nulinę nuorodą.

išvada

Taigi žengėme dar vieną mažą žingsnelį – dabar naudotis PVS-Studio tapo dar lengviau ir patogiau. Taip pat norėčiau pasakyti, kad „Chocolatey“ yra geras paketų tvarkyklė, turinti nedaug klaidų kode, kurių gali būti dar mažiau naudojant PVS-Studio.

Kviečiame atsisiųsti ir išbandykite PVS-Studio. Reguliarus statinio analizatoriaus naudojimas pagerins jūsų komandos kuriamo kodo kokybę ir patikimumą bei padės išvengti daugelio nulinės dienos pažeidžiamumas.

PS

Prieš paskelbdami straipsnį išsiuntėme „Chocolatey“ kūrėjams ir jie jį gerai gavo. Mes neradome nieko kritiško, bet jiems, pavyzdžiui, patiko mūsų rasta klaida, susijusi su „api-key“ raktu.

„PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas iš „Azure DevOps“

Jei norite pasidalinti šiuo straipsniu su angliškai kalbančia auditorija, naudokite vertimo nuorodą: Vladislav Stolyarov. „PVS-Studio“ dabar yra „Chocolatey“: „Chocolatey“ tikrinimas naudojant „Azure DevOps“..

Šaltinis: www.habr.com

Добавить комментарий