PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps
Naďalej robíme používanie PVS-Studio pohodlnejším. Náš analyzátor je teraz k dispozícii v Chocolatey, správcovi balíkov pre Windows. Veríme, že to uľahčí nasadenie PVS-Studio najmä v cloudových službách. Aby sme nezašli ďaleko, skontrolujeme zdrojový kód tej istej Chocolatey. Azure DevOps bude fungovať ako systém CI.

Tu je zoznam našich ďalších článkov na tému integrácie s cloudovými systémami:

Odporúčam vám venovať pozornosť prvému článku o integrácii s Azure DevOps, pretože v tomto prípade sú niektoré body vynechané, aby sa neduplikovali.

Takže, hrdinovia tohto článku:

Štúdio PVS je nástroj na analýzu statického kódu určený na identifikáciu chýb a potenciálnych zraniteľností v programoch napísaných v C, C++, C# a Java. Beží na 64-bitových systémoch Windows, Linux a macOS a dokáže analyzovať kód navrhnutý pre 32-bitové, 64-bitové a vstavané platformy ARM. Ak je to prvýkrát, čo skúšate statickú analýzu kódu na kontrolu vašich projektov, odporúčame vám, aby ste sa s ňou oboznámili článok o tom, ako rýchlo zobraziť najzaujímavejšie upozornenia PVS-Studio a vyhodnotiť možnosti tohto nástroja.

Azure DevOps — súbor cloudových služieb, ktoré spoločne pokrývajú celý vývojový proces. Táto platforma obsahuje nástroje ako Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, ktoré umožňujú urýchliť proces tvorby softvéru a zlepšiť jeho kvalitu.

Chocolatey je správca balíkov s otvoreným zdrojovým kódom pre Windows. Cieľom projektu je zautomatizovať celý životný cyklus softvéru od inštalácie až po aktualizáciu a odinštalovanie na operačných systémoch Windows.

O používaní Chocolatey

Tu môžete vidieť, ako nainštalovať samotného správcu balíkov odkaz. Kompletná dokumentácia pre inštaláciu analyzátora je dostupná na odkaz Pozrite si časť Inštalácia pomocou správcu balíkov Chocolatey. Stručne zopakujem niektoré body odtiaľ.

Príkaz na inštaláciu najnovšej verzie analyzátora:

choco install pvs-studio

Príkaz na inštaláciu konkrétnej verzie balíka PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Štandardne je nainštalované iba jadro analyzátora, komponent Core. Všetky ostatné príznaky (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) je možné odovzdať pomocou --package-parameters.

Príklad príkazu, ktorý nainštaluje analyzátor s doplnkom pre Visual Studio 2019:

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

Teraz sa pozrime na príklad pohodlného použitia analyzátora v rámci Azure DevOps.

nastavenie

Dovoľte mi pripomenúť, že existuje samostatná sekcia o takých problémoch, ako je registrácia účtu, vytvorenie Build Pipeline a synchronizácia vášho účtu s projektom umiestneným v úložisku GitHub. článok. Naše nastavenie okamžite začne zápisom konfiguračného súboru.

Najprv nastavíme spúšťač spustenia, ktorý označuje, že spúšťame iba zmeny v majster pobočka:

trigger:
- master

Ďalej musíme vybrať virtuálny stroj. Zatiaľ to bude agent hostený spoločnosťou Microsoft so systémom Windows Server 2019 a Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Prejdime k telu konfiguračného súboru (blok kroky). Napriek tomu, že do virtuálneho počítača nemôžete nainštalovať ľubovoľný softvér, nepridal som kontajner Docker. Môžeme pridať Chocolatey ako rozšírenie pre Azure DevOps. Ak to chcete urobiť, poďme na odkaz. Kliknite Dostaň to zadarmo. Ďalej, ak už máte autorizáciu, jednoducho vyberte svoj účet, a ak nie, urobte to isté po autorizácii.

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Tu musíte vybrať, kam rozšírenie pridáme, a kliknúť na tlačidlo inštalovať.

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Po úspešnej inštalácii kliknite Pokračujte do organizácie:

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Teraz môžete v okne vidieť šablónu úlohy Chocolatey úlohy pri úprave konfiguračného súboru azure-pipelines.yml:

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Kliknite na Chocolatey a pozrite si zoznam polí:

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Tu si musíme vybrať inštalovať v teréne s tímami. IN Názov súboru Nuspec uveďte názov požadovaného balíka – pvs-studio. Ak neuvediete verziu, nainštaluje sa najnovšia, čo nám úplne vyhovuje. Stlačíme tlačidlo pridať a vygenerovanú úlohu uvidíme v konfiguračnom súbore.

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

Ďalej prejdime k hlavnej časti nášho súboru:

- task: CmdLine@2
  inputs:
    script: 

Teraz musíme vytvoriť súbor s licenciou analyzátora. Tu PVSNAME и PVSKEY – názvy premenných, ktorých hodnoty zadávame v nastaveniach. Uložia si prihlasovací a licenčný kľúč PVS-Studio. Ak chcete nastaviť ich hodnoty, otvorte ponuku Premenné->Nová premenná. Vytvorme premenné PVSNAME na prihlásenie a PVSKEY pre kľúč analyzátora. Nezabudnite zaškrtnúť políčko Udržujte túto hodnotu v tajnosti pre PVSKEY. Príkazový kód:

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

Poďme zostaviť projekt pomocou súboru bat umiestneného v úložisku:

сall build.bat

Vytvorme priečinok, do ktorého sa budú ukladať súbory s výsledkami analyzátora:

сall mkdir PVSTestResults

Začnime analyzovať projekt:

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

Náš prehľad konvertujeme do formátu html pomocou nástroja PlogСonverter:

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

Teraz musíte vytvoriť úlohu, aby ste mohli nahrať správu.

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

Kompletný konfiguračný súbor vyzerá takto:

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

Poďme kliknúť Uložiť->Uložiť->Spustiť spustiť úlohu. Prejdeme na kartu úloh a stiahneme si prehľad.

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Projekt Chocolatey obsahuje iba 37615 riadkov kódu C#. Pozrime sa na niektoré nájdené chyby.

Výsledky testu

Upozornenie N1

Varovanie analyzátora: V3005 Premenná 'Provider' je priradená sama sebe. CrytpoHashProviderSpecs.cs 38

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

Analyzátor zistil priradenie premennej k sebe, čo nedáva zmysel. S najväčšou pravdepodobnosťou by namiesto jednej z týchto premenných mala existovať iná. Alebo ide o preklep a priradenie navyše možno jednoducho odstrániť.

Upozornenie N2

Varovanie analyzátora: V3093 [CWE-480] Operátor '&' vyhodnocuje oba operandy. Možno by sa mal namiesto toho použiť skratový operátor '&&'. 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;
  }
}

Rozdiel medzi operátormi & od operátora && je, že ak je ľavá strana výrazu nepravdivý, potom sa bude stále počítať pravá strana, čo v tomto prípade znamená zbytočné volania metód system.directory_exists.

V uvažovanom fragmente ide o drobnú chybu. Áno, tento stav je možné optimalizovať nahradením operátora & operátorom &&, ale z praktického hľadiska to nič neovplyvňuje. V iných prípadoch však zámena medzi & a && môže spôsobiť vážne problémy, keď sa pravá strana výrazu ošetrí nesprávnymi/neplatnými hodnotami. Napríklad v našom súbore chýb identifikované pomocou diagnostiky V3093, je tu tento prípad:

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

Aj keď index k je nesprávny, použije sa na prístup k prvku poľa. V dôsledku toho sa vyvolá výnimka IndexOutOfRangeException.

Výstrahy N3, N4

Varovanie analyzátora: V3022 [CWE-571] Výraz 'shortPrompt' je vždy pravdivý. InteractivePrompt.cs 101
Varovanie analyzátora: V3022 [CWE-571] Výraz 'shortPrompt' je vždy pravdivý. 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 tomto prípade sa za fungovaním ternárneho operátora skrýva zvláštna logika. Pozrime sa bližšie: ak je splnená podmienka, ktorú som označil číslom 1, potom prejdeme na podmienku 2, ktorá je vždy pravdivý, čo znamená, že sa vykoná riadok 3. Ak sa podmienka 1 ukáže ako nepravdivá, prejdeme na riadok označený číslom 4, pričom podmienka je vždy pravdivý, čo znamená, že sa vykoná riadok 5. Nikdy teda nebudú splnené podmienky označené komentárom 0, čo nemusí byť presne taká logika činnosti, akú programátor očakával.

Upozornenie N5

Varovanie analyzátora: V3123 [CWE-783] Operátor '?:' možno funguje iným spôsobom, ako sa očakávalo. Jeho priorita je nižšia ako priorita ostatných operátorov v jeho stave. 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 fungovala pre linku:

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

Keďže premenná j o pár riadkov vyššie sa inicializuje na nulu, ternárny operátor vráti hodnotu nepravdivý. Kvôli tejto podmienke sa telo cyklu vykoná iba raz. Zdá sa mi, že tento kus kódu vôbec nefunguje tak, ako to programátor zamýšľal.

Upozornenie N6

Varovanie analyzátora: V3022 [CWE-571] Výraz 'installedPackageVersions.Count != 1' je vždy pravdivý. 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);
    }
    ....
  }
  ....
}

Je tu zvláštny vnorený stav: installPackageVersions.Count != 1čo bude vždy pravdivý. Takéto varovanie často naznačuje logickú chybu v kóde av iných prípadoch jednoducho naznačuje nadbytočnú kontrolu.

Upozornenie N7

Varovanie analyzátora: V3001 Naľavo a napravo od výrazu „||“ sú rovnaké podvýrazy 'commandArguments.contains("-apikey")' operátor. 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");
}

Programátor, ktorý napísal túto časť kódu, skopíroval a vložil posledné dva riadky a zabudol ich upraviť. Z tohto dôvodu nemohli používatelia Chocolatey použiť parameter apikey ešte pár spôsobov. Podobne ako vyššie uvedené parametre môžem ponúknuť nasledujúce možnosti:

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

Chyby kopírovania a vkladania majú veľkú šancu, že sa skôr či neskôr objavia v akomkoľvek projekte s veľkým množstvom zdrojového kódu a jedným z najlepších nástrojov na boj proti nim je statická analýza.

PS A ako vždy, táto chyba sa zvykne objaviť na konci viacriadkovej podmienky :). Pozri publikáciu "Efekt posledného riadku".

Upozornenie N8

Varovanie analyzátora: V3095 [CWE-476] Objekt 'installedPackage' bol použitý predtým, ako bol overený na hodnotu null. Kontrolné riadky: 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)
  {
    ....
  }
  ....
}

Klasická chyba: najprv objekt nainštalovaný balík sa používa a potom sa kontroluje null. Táto diagnostika nám hovorí o jednom z dvoch problémov v programe: buď nainštalovaný balík nikdy rovný null, čo je pochybné, a potom je kontrola nadbytočná, alebo by sme mohli potenciálne dostať vážnu chybu v kóde - pokus o prístup k nulovej referencii.

Záver

Takže sme urobili ďalší malý krok - teraz je používanie PVS-Studio ešte jednoduchšie a pohodlnejšie. Chcel by som tiež povedať, že Chocolatey je dobrý správca balíkov s malým počtom chýb v kóde, ktorých by pri používaní PVS-Studio mohlo byť ešte menej.

Blikal k stiahnutiu a skúste PVS-Studio. Pravidelné používanie statického analyzátora zlepší kvalitu a spoľahlivosť kódu vyvinutého vaším tímom a pomôže mnohým predchádzať zero day zraniteľnosti.

PS

Pred uverejnením sme článok poslali vývojárom Chocolatey a tí ho prijali dobre. Nenašli sme nič kritické, ale napríklad sa im páčila chyba, ktorú sme našli v súvislosti s kľúčom „api-key“.

PVS-Studio je teraz v Chocolatey: kontroluje Chocolatey z Azure DevOps

Ak chcete zdieľať tento článok s anglicky hovoriacim publikom, použite odkaz na preklad: Vladislav Stolyarov. PVS-Studio je teraz vo verzii Chocolatey: Kontrola čokolády v rámci Azure DevOps.

Zdroj: hab.com

Pridať komentár