PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps
Nenehajamo, da bi uporaba PVS-Studio postala lažja. Zdaj je naš analizator na voljo v Chocolatey, upravitelju paketov za Windows. Prepričani smo, da bo to olajšalo uvedbo PVS-Studio, zlasti v oblačnih storitvah. Da se ne bi oddaljevali, bomo preverili izvorno kodo istega Chocolatey-ja. Azure DevOps bo služil kot CI sistem.

Tukaj je seznam naših drugih člankov o integraciji z oblačnimi sistemi:

Priporočam, da se osredotočite na prvi članek o integraciji z Azure DevOps, ker so nekatere točke v tem primeru izpuščene, da se ne bi ponavljali.

Torej, junaki tega članka:

PVS-Studio — orodje za statično analizo kode, namenjeno odkrivanju napak in potencialnih ranljivosti v programih, napisanih v C, C++, C# in Java. Deluje v 64-bitnih sistemih na Windows, Linux in macOS ter lahko analizira kodo, namenjeno 32-bitnim, 64-bitnim in vgrajenim ARM platformam. Če prvič preizkušate statično analizo kode za preverjanje svojih projektov, priporočamo, da se seznanite s статьёй o tem, kako hitro pregledati najzanimivejša opozorila PVS-Studio in oceniti možnosti tega orodja.

Azure DevOps — nabor oblačnih storitev, ki pokrivajo celoten proces razvoja. Ta platforma vključuje orodja, kot so Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, ki omogočajo pospešitev procesa razvoja programske opreme in izboljšanje njene kakovosti.

Chocolatey – upravitelj paketov za Windows z odprto kodo. Cilj projekta je avtomatizirati celoten življenjski cikel programske opreme od namestitve do posodabljanja in odstranjevanja v operacijskih sistemih Windows.

O uporabi Chocolatey

Oglejte si, kako namestiti sam upravitelj paketov, lahko na tej linku. Popolna dokumentacija za namestitev analizatorja je na voljo na linku v razdelku „Namestitev z uporabo upravitelja paketov Chocolatey“. Na kratko bom ponovil nekatere točke od tam.

Ukaz za namestitev zadnje različice analizatorja:

choco install pvs-studio

Ukaz za namestitev določene različice paketa PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Privzeto se namesti samo jedro analizatorja — komponenta Core. Vse ostale oznake (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) je mogoče posredovati z uporabo —package-parameters.

Primer ukaza, ki bo namestil analizator s dodatkom za Visual Studio 2019:

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

Sedaj poglejmo primer enostavne uporabe analizatorja v Azure DevOps.

Setup

Spomnim, da so za take zadeve, kot so registracija računa, ustvarjanje Build Pipeline in sinhronizacija računa s projektom v repozitoriju na GitHubu, na voljo posebne članek. Naša nastavitev se bo takoj začela s pisanjem konfiguracijske datoteke.

Najprej nastavimo sprožilec, tako da določimo, da se sprožitev izvede samo za spremembe v master veji:

trigger:
- master

Nato moramo izbrati virtualni stroj. V tem trenutku bo to Microsoftov gostujoči agent z Windows Server 2019 in Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Poglejmo telo konfiguracijske datoteke (blok steps). Kljub temu, da na virtualni stroj ni mogoče namestiti poljubne programske opreme, nisem dodal Docker kontejnerja. Chocolatey lahko dodamo kot razširitev za Azure DevOps. Zato gremo na linku. Kliknemo Get it free. Če ste že prijavljeni, preprosto izberite svoj račun, sicer pa naredite vse to po prijavi.

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Tukaj je treba izbrati, kam dodamo razširitev, in pritisniti gumb Namestite.

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Po uspešni namestitvi kliknite Proceed to organization:

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Zdaj lahko vidite predlogo za nalogo Chocolatey v oknu naloge med urejanjem konfiguracijske datoteke azure-pipelines.yml:

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Kliknimo na Chocolatey in videli bomo seznam polj:

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Tukaj moramo izbrati install v polju z ukazi. V Nuspec File Name bomo navedli ime potrebnega paketa – pvs-studio. Če ne navedemo različice, se bo namestila najnovejša, kar nas povsem zadostuje. Kliknite na gumb add in videli bomo oblikovano nalogo v konfiguracijski datoteki.

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

Nato se premaknemo na glavni del naše datoteke:

- task: CmdLine@2
  inputs:
    script: 

Sedaj moramo ustvariti datoteko z licenco analizatorja. Tukaj PVSNAME in PVSKEY – sta imeni spremenljivk, katerih vrednosti bomo navedli v nastavitvah. Shranjevala bosta uporabniško ime in licenčni ključ PVS-Studio. Da določimo njihovo vrednost, odprite meni Variables->New variable. Ustvarimo spremenljivke PVSNAME za uporabniško ime in PVSKEY za ključa analize. Ne pozabite označiti kljukice Ohranite to vrednost v skrivnosti za PVSKEY. Ukazna koda:

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

Zgradimo projekt s pomočjo bat datoteke, ki se nahaja v repozitoriju:

kličite build.bat

Ustvarimo mapo, kjer bodo shranjene datoteke z rezultati dela analizerja:

kličite mkdir PVSTestResults

Zagnali bomo analizo projekta:

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

Pretvorimo našo poročilo v html format s pomočjo orodja PlogConverter:

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

Sedaj je potrebno ustvariti nalogo, da lahko izvozimo poročilo.

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

Celotna konfiguracijska datoteka izgleda takole:

trigger:
- master

pool:
  vmImage: 'windows-latest'

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

- task: CmdLine@2
  inputs:
    script: |
      kličite "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      credentials –u $(PVSNAME) –n $(PVSKEY)
      kličite build.bat
      kličite mkdir PVSTestResults
      kličite "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      –t .srcchocolatey.sln –o .PVSTestResultsChoco.plog
      kličite "C:Program Files (x86)PVS-StudioPlogConverter.exe" 
      –t html –o .PVSTestResults .PVSTestResultsChoco.plog

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

Pritisnite Shrani->Shrani->Zagon za zagon naloge. Izvozimo poročilo, ko preidemo na zavihek naloge.

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Projekt Chocolatey vsebuje skupno 37615 vrstic C# kode. Oglejmo si nekatere od najdenih napak.

Rezultati preverjanja

Предупреждение N1

Opozorilo analizerja: V3005 Spremenljivka 'Provider' je dodeljena sama sebi. CrytpoHashProviderSpecs.cs 38

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

Analizator je odkril dodelitev spremenljivki sami sebi, kar nima smisla. Verjetno bi na mestu ene od teh spremenljivk morala biti neka druga. Morda gre za tipkarsko napako in nepotrebno dodelitev lahko enostavno odstranimo.

Предупреждение N2

Opozorilo analizerja: V3093 [CWE-480] Operator '&' ovrednoti oba operanda. Morda bi bilo bolje uporabiti skrajšani operator '&&'. 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;
  }
}

Razlika med operatorjem & in operatorjem && je v tem, da če je leva stran izraza — false, vendar se bo kljub temu izračunala desna stran, kar v tem primeru pomeni nepotrebne klice metode system.directory_exists.

V obravnavanem fragmentu gre za manjšo napako. Da, to stanje je mogoče optimizirati, tako da operater & postavimo na operater &&, vendar praktično to ne vpliva na nič. Vendar pa v drugih primerih zmeda med & in && lahko povzroči resne težave, ko bo desna stran izraza obravnavala nepravilne/nedosledne vrednosti. Na primer, v naši zbirki napak, odkritih s pomočjo diagnostike V3093, imamo tak primer:

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

Tudi če je indeks k nepravilen, se bo uporabljal za dostop do elementa niza. Posledica bo generiranje izjeme IndexOutOfRangeException.

Opozorila N3, N4

Opozorilo analizerja: V3022 [CWE-571] Izraz 'shortPrompt' je vedno resničen. InteractivePrompt.cs 101
Opozorilo analizerja: V3022 [CWE-571] Izraz 'shortPrompt' je vedno resničen. 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
    ....
  }
  ....
}

V tem primeru je prisotna čudna logika delovanja ternega operatorja. Poglejmo podrobneje: če bo izpolnjeno stanje, označeno z mojo številko 1, bomo prešli na stanje 2, ki je vedno true, kar pomeni, da se bo izvajala vrstica 3. Če pa se izkaže, da je stanje 1 lažno, bomo prešli na vrstico, označeno s številko 4, kjer je stanje prav tako vedno true, kar pomeni, da se bo izvajala vrstica 5. Tako pogoji, označeni s komentarjem 0, nikoli ne bodo izpolnjeni, kar morda ni povsem logika, na katero je programer računal.

Opozorilo N5

Opozorilo analizerja: V3123 [CWE-783] Morda operator '?:' deluje drugače, kot je bilo pričakovano. Njegova prioriteta je nižja od prioritete drugih operatorjev v njegovem stanju. 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);
  }
}

Diagnostika je delovala na vrstico:

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

Ker je spremenljivka vrednost Nekaj vrstic višje se inicializira na nič, ternarni operator bo vrnil vrednost false. Zaradi te omejitve se telo zanke izvede le enkrat. Zdi se mi, da ta del kode ne deluje tako, kot je programer nameraval.

Opozorilo N6

Opozorilo analizerja: V3022 [CWE-571] Izraz ‘installedPackageVersions.Count != 1’ je vedno resničen. NugetService.cs 1405

private void remove_nuget_cache_for_package(....)
{
  if (!config.AllVersions && installedPackageVersions.Count > 1)
  {
    const string allVersionsChoice = "Vse različice";
    if (installedPackageVersions.Count != 1)
    {
      choices.Add(allVersionsChoice);
    }
    ....
  }
  ....
}

Tukaj je čudna vgrajena omejitev: installedPackageVersions.Count != 1, ki bo vedno true. Pogosto takšno opozorilo kaže na logično napako v kodi, v drugih primerih pa na nepotrebno preverjanje.

Opozorilo N7

Opozorilo analizerja: V3001 Obstajajo identične podizrazitve ‘commandArguments.contains("-apikey")’ na levi in desni strani operatorja ‘||’. 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");
}

Programer, ki je napisal ta del kode, je kopiral zadnje dve vrstici in pozabil, da ju uredil. Zelo zaradi tega so uporabniki Chocolatey izgubili možnost uporabe parametra apikey še na nekaj načinov. Podobno kot pri zgornjih parametrih, lahko predlagam take možnosti:

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

Napačne kopije in prilepi napake se lahko zgodijo ob katerikoli priložnosti v projektu z obsežno kodo, in eno najboljših orodij za boj proti njim je statična analiza.

P.S. In kot vedno, ta napaka običajno nastane na koncu večvrstne omejitve :). Oglejte si objavo "Učinek zadnje vrstice".

Opozorilo N8

Opozorilo analizerja: V3095 [CWE-476] Objekt ‘installedPackage’ je bil uporabljen, preden je bil preverjen proti null. Preverite vrstice: 910, 917. NugetService.cs 910

javni virtualni 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)
  {
    ....
  }
  ....
}

Klasična greška: prvo se koristi objekat installedPackage a zatim se proverava na null. Ova dijagnostika nam ukazuje na jedan od dva problema u programu: ili installedPackage nikada nije jednak null, što je sumnjivo, i tada je provera suvišna, ili potencijalno možemo dobiti ozbiljnu grešku u kodu – pokušaj pristupa nul referenci.

Zaključek

Eto, napravili smo još jedan mali korak – sada je korišćenje PVS-Studio još lakše i prijatnije. Takođe želim reći da je Chocolatey dobar paket menadžer sa malim brojem grešaka u kodu, kojih bi moglo biti još manje korišćenjem PVS-Studio.

Vabimo vas prenesti i isprobati PVS-Studio. Redovno korišćenje statičkog analizatora povećaće kvalitet i pouzdanost koda koji vaša ekipa razvija i pomoći u prevenciji mnogih ulaganja nultog dana.

P.S.

Pre objavljivanja, poslali smo članak programerima Shocolatey, i oni su ga dobro prihvatili. Nije pronađeno ništa kritično, ali im je, na primer, bila zanimljiva greška koju smo otkrili vezano za ključ "api-key".

PVS-Studio теперь в Chocolatey: проверка Chocolatey из-под Azure DevOps

Če želite to besedilo deliti z angleško govorečo publiko, vas prosim, da uporabite povezavo na prevod: Vladislav Stolyarov. PVS-Studio je sada u Chocolatey: Proveravanje Chocolatey pod Azure DevOps.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster