PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps
Pokračujeme ve zpříjemňování používání PVS-Studio. Náš analyzátor je nyní k dispozici v Chocolatey, správci balíčků pro Windows. Věříme, že to usnadní nasazení PVS-Studio zejména v cloudových službách. Abychom nezašli daleko, podívejme se na zdrojový kód stejného Chocolatey. Azure DevOps bude fungovat jako systém CI.

Zde je seznam našich dalších článků na téma integrace s cloudovými systémy:

Doporučuji vám věnovat pozornost prvnímu článku o integraci s Azure DevOps, protože v tomto případě jsou některé body vynechány, aby nebyly duplikovány.

Takže hrdinové tohoto článku:

Studio PVS je nástroj pro analýzu statického kódu určený k identifikaci chyb a potenciálních zranitelností v programech napsaných v C, C++, C# a Java. Běží na 64bitových systémech Windows, Linux a macOS a dokáže analyzovat kód navržený pro 32bitové, 64bitové a vestavěné platformy ARM. Pokud je to poprvé, co zkoušíte statickou analýzu kódu pro kontrolu vašich projektů, doporučujeme vám se s tím seznámit článek o tom, jak rychle zobrazit nejzajímavější varování PVS-Studio a vyhodnotit možnosti tohoto nástroje.

Azure DevOps — soubor cloudových služeb, které společně pokrývají celý vývojový proces. Tato platforma zahrnuje nástroje jako Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, které vám umožní urychlit proces tvorby softwaru a zlepšit jeho kvalitu.

Čokoláda je správce balíčků s otevřeným zdrojovým kódem pro Windows. Cílem projektu je automatizace celého životního cyklu softwaru od instalace až po aktualizaci a odinstalaci na operačních systémech Windows.

O používání Chocolatey

Zde můžete vidět, jak nainstalovat samotného správce balíčků odkaz. Kompletní dokumentace pro instalaci analyzátoru je k dispozici na odkaz Viz část Instalace pomocí správce balíčků Chocolatey. Krátce zopakuji některé body odtud.

Příkaz k instalaci nejnovější verze analyzátoru:

choco install pvs-studio

Příkaz k instalaci konkrétní verze balíčku PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Ve výchozím nastavení je nainstalováno pouze jádro analyzátoru, komponenta Core. Všechny ostatní příznaky (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) lze předat pomocí --package-parameters.

Příklad příkazu, který nainstaluje analyzátor s pluginem pro Visual Studio 2019:

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

Nyní se podívejme na příklad pohodlného použití analyzátoru v Azure DevOps.

Nastavení

Dovolte mi připomenout, že existuje samostatná sekce o takových problémech, jako je registrace účtu, vytvoření Build Pipeline a synchronizace vašeho účtu s projektem umístěným v úložišti GitHub. článek. Naše nastavení okamžitě začne zápisem konfiguračního souboru.

Nejprve nastavíme spouštěcí spouštěč, což znamená, že spouštíme pouze pro změny v mistr větev:

trigger:
- master

Dále musíme vybrat virtuální stroj. Prozatím to bude agent hostovaný společností Microsoft s Windows Server 2019 a Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Přejděme k tělu konfiguračního souboru (blok kroky). Navzdory skutečnosti, že do virtuálního počítače nemůžete nainstalovat libovolný software, nepřidal jsem kontejner Docker. Můžeme přidat Chocolatey jako rozšíření pro Azure DevOps. Chcete-li to provést, pojďme na odkaz. Klikněte Dostat to zdarma. Dále, pokud jste již autorizováni, jednoduše vyberte svůj účet, a pokud ne, proveďte to samé po autorizaci.

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Zde musíte vybrat, kam přidáme rozšíření, a kliknout na tlačítko instalovat.

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Po úspěšné instalaci klikněte Pokračujte k organizaci:

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Nyní můžete v okně vidět šablonu pro úlohu Chocolatey úkoly při úpravě konfiguračního souboru azure-pipelines.yml:

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Klikněte na Chocolatey a zobrazte seznam polí:

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Zde musíme vybrat instalovat v terénu s týmy. V Název souboru Nuspec uveďte název požadovaného balíčku – pvs-studio. Pokud verzi neuvedete, nainstaluje se nejnovější, což nám plně vyhovuje. Zmáčkneme tlačítko přidat a vygenerovanou úlohu uvidíme v konfiguračním souboru.

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

Dále přejdeme k hlavní části našeho souboru:

- task: CmdLine@2
  inputs:
    script: 

Nyní musíme vytvořit soubor s licencí analyzátoru. Tady PVSNAME и PVSKEY – názvy proměnných, jejichž hodnoty zadáme v nastavení. Uloží přihlašovací a licenční klíč PVS-Studio. Chcete-li nastavit jejich hodnoty, otevřete nabídku Proměnné->Nová proměnná. Pojďme vytvořit proměnné PVSNAME pro přihlášení a PVSKEY pro klíč analyzátoru. Nezapomeňte zaškrtnout políčko Udržujte tuto hodnotu v tajnosti pro PVSKEY. příkazový kód:

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

Pojďme sestavit projekt pomocí souboru bat umístěného v úložišti:

сall build.bat

Vytvořme složku, kam se budou ukládat soubory s výsledky analyzátoru:

сall mkdir PVSTestResults

Začněme analyzovat projekt:

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

Naši zprávu převedeme do formátu html pomocí nástroje PlogСonverter:

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

Nyní musíte vytvořit úlohu, abyste mohli nahrát zprávu.

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

Kompletní konfigurační soubor vypadá 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()

Pojďme kliknout Uložit->Uložit->Spustit spustit úlohu. Přejdeme na kartu úkolů a stáhneme si přehled.

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Projekt Chocolatey obsahuje pouze 37615 řádků kódu C#. Podívejme se na některé nalezené chyby.

Výsledky testů

Varování N1

Upozornění analyzátoru: V3005 Proměnná 'Provider' je přiřazena sama sobě. CrytpoHashProviderSpecs.cs 38

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

Analyzátor zjistil přiřazení proměnné k sobě, což nedává smysl. S největší pravděpodobností by místo jedné z těchto proměnných měla být nějaká jiná. Nebo se jedná o překlep a nadbytečné přiřazení lze jednoduše odstranit.

Varování N2

Upozornění analyzátoru: V3093 [CWE-480] Operátor '&' vyhodnocuje oba operandy. Možná by měl být místo toho použit zkratovací 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;
  }
}

Rozdíl mezi operátory & od operátora && je, že pokud je levá strana výrazu nepravdivý, pak se bude stále počítat pravá strana, což v tomto případě znamená zbytečná volání metod system.directory_exists.

V uvažovaném fragmentu jde o drobnou vadu. Ano, tento stav lze optimalizovat nahrazením operátoru & operátorem &&, ale z praktického hlediska to nic neovlivňuje. V jiných případech však záměna mezi & a && může způsobit vážné problémy, když je pravá strana výrazu ošetřena nesprávnými/neplatnými hodnotami. Například v našem souboru chyb identifikované pomocí diagnostiky V3093, je tento případ:

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

I když index k je nesprávný, bude použit pro přístup k prvku pole. V důsledku toho bude vyvolána výjimka IndexOutOfRangeException.

Varování N3, N4

Upozornění analyzátoru: V3022 [CWE-571] Výraz 'shortPrompt' je vždy pravdivý. InteractivePrompt.cs 101
Upozornění analyzátoru: 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 případě se za operací ternárního operátoru skrývá podivná logika. Podívejme se blíže: pokud je splněna podmínka, kterou jsem označil číslem 1, pak přejdeme k podmínce 2, která je vždy pravdivý, což znamená, že bude proveden řádek 3. Pokud se podmínka 1 ukáže jako nepravdivá, pak přejdeme na řádek označený číslem 4, podmínka, ve které je také vždy pravdivý, což znamená, že bude proveden řádek 5. Nikdy tedy nebudou splněny podmínky označené komentářem 0, což nemusí být přesně ta logika operace, kterou programátor očekával.

Varování N5

Upozornění analyzátoru: V3123 [CWE-783] Operátor '?:' možná funguje jiným způsobem, než se očekávalo. Jeho priorita je nižší než priorita ostatních operátorů v jeho stavu. 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 pro linku:

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

Vzhledem k tomu, že proměnná j o pár řádků výše je inicializováno na nulu, ternární operátor vrátí hodnotu nepravdivý. Kvůli této podmínce bude tělo smyčky provedeno pouze jednou. Zdá se mi, že tento kus kódu vůbec nefunguje tak, jak programátor zamýšlel.

Varování N6

Upozornění analyzátoru: 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);
    }
    ....
  }
  ....
}

Zde je zvláštní vnořená podmínka: installPackageVersions.Count != 1který bude vždy pravdivý. Takové varování často ukazuje na logickou chybu v kódu a v jiných případech pouze na nadbytečnou kontrolu.

Varování N7

Upozornění analyzátoru: V3001 Nalevo a napravo od '||' jsou identické 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, který napsal tuto část kódu, zkopíroval a vložil poslední dva řádky a zapomněl je upravit. Z tohoto důvodu nemohli uživatelé Chocolatey použít parametr apikey ještě pár způsobů. Podobně jako u výše uvedených parametrů mohu nabídnout následující možnosti:

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

Chyby kopírování a vkládání mají vysokou šanci, že se dříve nebo později objeví v jakémkoli projektu s velkým množstvím zdrojového kódu a jedním z nejlepších nástrojů, jak s nimi bojovat, je statická analýza.

PS A jako vždy tato chyba má tendenci se objevit na konci víceřádkové podmínky :). Viz publikace "Efekt posledního řádku".

Varování N8

Upozornění analyzátoru: V3095 [CWE-476] Objekt 'installedPackage' byl použit předtím, než byl ověřen proti nule. Kontrolní řádky: 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: objekt první nainstalovaný balíček se používá a poté se kontroluje null. Tato diagnostika nás informuje o jednom ze dvou problémů v programu: buď nainstalovaný balíček nikdy rovné null, což je pochybné, a pak je kontrola nadbytečná, nebo bychom mohli potenciálně dostat vážnou chybu v kódu - pokus o přístup k nulové referenci.

Závěr

Udělali jsme tedy další malý krok – nyní je používání PVS-Studio ještě jednodušší a pohodlnější. Rád bych také řekl, že Chocolatey je dobrý správce balíčků s malým počtem chyb v kódu, kterých by při použití PVS-Studio mohlo být ještě méně.

Zveme ke stažení a zkuste PVS-Studio. Pravidelné používání statického analyzátoru zlepší kvalitu a spolehlivost kódu, který váš tým vyvíjí, a pomůže zabránit mnoha zranitelnosti zero day.

PS

Před zveřejněním jsme článek zaslali vývojářům Chocolatey a ti jej přijali dobře. Nenašli jsme nic kritického, ale jim se například líbila chyba, kterou jsme našli v souvislosti s klíčem „api-key“.

PVS-Studio je teď v Chocolatey: kontrola Chocolatey z Azure DevOps

Pokud chcete tento článek sdílet s anglicky mluvícím publikem, použijte prosím odkaz na překlad: Vladislav Stolyarov. PVS-Studio je nyní v Chocolatey: Kontrola Chocolatey v Azure DevOps.

Zdroj: www.habr.com

Přidat komentář