PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps
Mēs turpinām padarīt PVS-Studio lietošanu ērtāku. Tagad mūsu analizators ir pieejams Chocolatey, pakotņu pārvaldniekā Windows. Mēs uzskatām, ka tas atvieglos PVS-Studio izvietošanu, it īpaši mākoņservisos. Lai tālu neietu, pārbaudīsim paša Chocolatey avota kodu. CI sistēma būs Azure DevOps.

Šeit ir saraksts ar citām mūsu rakstiem par integrāciju ar mākoņsistēmām:

Iesaku pievērst uzmanību pirmajam rakstam par integrāciju ar Azure DevOps, jo šajā gadījumā daži aspekti tika izlaisti, lai nerakstītu divreiz.

Tātad, šīs raksta varoņi:

PVS-Studio — statiskās analīzes rīks, kas paredzēts kļūdu un potenciālo ievainojamību noteikšanai programmās, kas uzrakstītas valodās C, C++, C# un Java. Darbojas 64 bitu sistēmās Windows, Linux un macOS, un var analizēt kodu, kas paredzēts 32 bitu, 64 bitu un iebūvētiem ARM platformām. Ja jūs pirmo reizi izmēģināt statisko koda analīzi, lai pārbaudītu savus projektus, mēs iesakām iepazīties ar rakstu par to, kā ātri apskatīt interesantākos PVS-Studio brīdinājumus un novērtēt šī rīka iespējas.

Azure DevOps — mākoņservisu komplekts, kas aptver visu izstrādes procesu. Šajā platformā ietilpst tādi rīki kā Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, kas ļauj paātrināt programmatūras izstrādes procesu un uzlabot tās kvalitāti.

Chocolatey — atvērtā koda pakotņu pārvaldnieks Windows. Projekta mērķis ir automatizēt visu programmatūras dzīves ciklu no instalēšanas līdz atjaunināšanai un dzēšanai Windows operētājsistēmās.

Par Chocolatey izmantošanu

Skatiet, kā instalēt pašu pakotņu pārvaldnieku, jūs varat šajā saišu. Pilna dokumentācija par analizatora instalēšanu ir pieejama saišu sadaļā "Instalācija, izmantojot pakotņu pārvaldnieku Chocolatey". Īsumā atkārtošu dažus tūrē.

Komanda, lai instalētu jaunāko analizatora versiju:

choco install pvs-studio

Komanda, lai instalētu konkrētu PVS-Studio pakotnes versiju:

choco install pvs-studio --version=7.05.35617.2075

Noklusējuma iestatījumi ir tikai analīzes motora komponents Core. Visus pārējos karogus (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) var nodot ar —package-parameters.

Piemērs komandas, kas instalēs analīzi ar paplašinājumu Visual Studio 2019:

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

Tagad aplūkosim ērtas analīzes izmantošanas piemiru Azure DevOps.

Iestatījumi

Atgādinu, ka tādi jautājumi kā konta reģistrācija, Build Pipeline veidošana un konta sinhronizācija ar projektu, kas atrodas GitHub repozitorijā, ir atsevišķi. raksts. Mūsu iestatīšana sāksies ar konfigurācijas faila rakstīšanu.

Sāksim ar palaišanas trigeru iestatīšanu, norādot, ka mēs uzsākam tikai izmaiņām. master lapu:

trigger:
- master

Tālāk mums jāizvēlas virtuālā mašīna. Šobrīd tā būs Microsoft-hosted aģents ar Windows Server 2019 un Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Pāriesim pie konfigurācijas faila satura (bloks steps). Neskaitoties no tā, ka virtuālajā mašīnā nevar instalēt nejaušu programmatūru, es neveicu Docker konteineru pievienošanu. Mēs varam pievienot Chocolatey kā paplašinājumu Azure DevOps. Lai to izdarītu, pāriesim uz saišu. Nospiedīsim Get it free. Pēc tam, ja esat jau autorizējies, vienkārši izvēlieties savu kontu, bet ja nē, tad veiciet to pašu pēc autorizācijas.

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Šeit ir jāizvēlas, kur pievienosim paplašinājumu, un jānospiež poga Instalēt.

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Pēc veiksmīgas instalācijas nospiedīsim Proceed to organization:

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Tagad varam redzēt Chocolatey uzdevuma veidni konfigurācijas faila rediģēšanas logā uzdevumi azure-pipelines.yml: Nospiedīsim uz Chocolatey un redzēsim lauku sarakstu:

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Šeit mums j選inās izvēlēties

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

komandu laukā. Laikā install Nuspec File Name norādīsim nepieciešamā pakotnes nosaukumu – pvs-studio. Ja versija netiks norādīta, tiks instalēta jaunākā, kas mums pilnībā apmierina. Nospiedīsim uz pogas un redzēsim izveidoto uzdevumu konfigurācijas failā. add steps: - task: ChocolateyCommand@0 inputs: command: 'install' installPackageId: 'pvs-studio'

Tālāk pāriesim pie mūsu faila galvenās daļas:

- task: CmdLine@2 inputs: script:

Tagad mums jāizveido licencēšanas fails analīzei. Šeit 

PVSNAME PVSKEY un – ir mainīgo nosaukumi, kuru vērtības mēs norādām iestatījumos. Tie glabās PVS-Studio pieteikšanās un licenci. Lai iestatītu to vērtības, atvērsim izvēlni Variables->New variable . Izveidosim mainīgospieteikšanās un PVSKEY lai pieteiktos un – ir mainīgo nosaukumi, kuru vērtības mēs norādām iestatījumos. Tie glabās PVS-Studio pieteikšanās un licenci. Lai iestatītu to vērtības, atvērsim izvēlni analizatora atslēgai. Neaizmirstiet atzīmēt rūtiņu Saglabājiet šo vērtību noslēpumā lai – ir mainīgo nosaukumi, kuru vērtības mēs norādām iestatījumos. Tie glabās PVS-Studio pieteikšanās un licenci. Lai iestatītu to vērtības, atvērsim izvēlni. Komandu kods:

saukt "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" akreditācijas 
–u $(PVSNAME) –n $(PVSKEY)

Sagatavosim projektu ar bat-failu, kas atrodas repozitorijā:

saukt build.bat

Izveidosim mapi, kurā tiks saglabāti analizatora darba rezultātu faili:

saukt mkdir PVSTestResults

Uzsāksim projekta analīzi:

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

Konvertēsim mūsu ziņojumu uz html formātu, izmantojot PlogConverter utilītu:

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

Tagad ir jāizveido uzdevums, lai varētu eksportēt ziņojumu.

- uzdevums: PublishBuildArtifacts@1
  ievadi:
    ceļšUzPublicēšanu: PVSTestResults
    artefaktaNosaukums: PVSTestResults
    nosacījums: vienmēr()

Pilns konfigurācijas fails izskatās šādi:

triggers:
- master

pool:
  vmImage: 'windows-latest'

solis:
- uzdevums: ChocolateyCommand@0
  ievadi:
    komanda: 'install'
    instalētPakasId: 'pvs-studio'

- uzdevums: CmdLine@2
  ievadi:
    skripts: |
      saukt "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      akreditācijas –u $(PVSNAME) –n $(PVSKEY)
      saukt build.bat
      saukt mkdir PVSTestResults
      saukt "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      –t .srcchocolatey.sln –o .PVSTestResultsChoco.plog
      saukt "C:Program Files (x86)PVS-StudioPlogConverter.exe" 
      –t html –o .PVSTestResults .PVSTestResultsChoco.plog

- uzdevums: PublishBuildArtifacts@1
  ievadi:
    ceļšUzPublicēšanu: PVSTestResults
    artefaktaNosaukums: PVSTestResults
    nosacījums: vienmēr()

Noklikšķināsim Saglabāt->Saglabāt->Palaist uzdevuma palaišanai. Eksportēsim ziņojumu, ieejot uzdevumu cilnē.

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Chocolatey projekts satur kopumā 37615 rindas C# koda. Apskatīsim dažas no atrastajām kļūdām.

Pārbaudes rezultāti

Brīdinājums N1

Analizatora brīdinājums: V3005 ‘Provider’ mainīgais tiek piešķirts pats sev. CrytpoHashProviderSpecs.cs 38

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

Analizators atklāja, ka mainīgais tiek piešķirts pats sev, kas nav jēgpilni. Visticamāk, kādā no šiem mainīgajiem vajadzētu būt citam mainīgajam. Vai nu tas ir drukas kļūda, un liekā piešķiršana vienkārši jāizdzēš.

Brīdinājums N2

Analizatora brīdinājums: V3093 [CWE-480] Operators ‘&’ novērtē abus operandus. Varbūt labāk izmantot īso shēmas operatoru ‘&&’. 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;
  }
}

Atšķirība starp operatoru & un operatoru && ir tajā, ka, ja kreisā izteiksmes daļa — false, tomēr tiks aprēķināta labā puse, kas šajā gadījumā nozīmē liekas metodes izsaukumus system.directory_exists.

Apskatītajā fragmentā tas ir neliels pārkāpums. Jā, šo nosacījumu var optimizēt, aizstājot operatoru & ar operatoru &&, bet praktiskā ziņā tam nav nekādas ietekmes. Tomēr citos gadījumos sajaukšana starp & un && var radīt nopietnas problēmas, kad labā puse izteiksmē strādā ar nederīgiem/vai nepieņemamiem vērtībām. Piemēram, mūsu kļūdu kolekcijā, kas tikuši atklāti ar diagnostiku V3093, ir šāds gadījums:

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

Pat ja indekss k ir nederīgs, tas tiks izmantots, lai piekļūtu masīva elementam. Rezultātā tiks ģenerēta izņēmuma IndexOutOfRangeException.

Brīdinājumi N3, N4

Analizatora brīdinājums: V3022 [CWE-571] Izteiksme ‘shortPrompt’ vienmēr ir patiess. InteractivePrompt.cs 101
Analizatora brīdinājums: V3022 [CWE-571] Izteiksme ‘shortPrompt’ vienmēr ir patiess. 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
    ....
  }
  ....
}

Šajā gadījumā ir dīvaina loģika ternārajam operatoram. Paskatīsimies detalizētāk: ja izpildīsies nosacījums, ko es esmu atzīmējis ar numuru 1, tad mēs pāriesim pie nosacījuma 2, kas vienmēr true, tādējādi izpildīsies rinda 3. Ja, tomēr, nosacījums 1 izrādīsies nepaties, tad mēs pāriesim uz rindu, ko esmu atzīmējis ar numuru 4, kur nosacījums arī vienmēr true, tādējādi izpildīsies rinda 5. Tādējādi nosacījumi, kuriem ir komentārs 0, nekad netiks izpildīti, kas var būt ne gluži tā loģika, uz kuru programmētājs cerēja.

Brīdinājums N5

Analizatora brīdinājums: V3123 [CWE-783] Iespējams, ka ‘?:’ operators darbojas citādāk, nekā gaidīts. Tā prioritāte ir zemāka nekā citu operatoru prioritāte tā nosacījumā. 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 aktivizējās uz rindu:

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

Tā kā mainīgais j Dažās rindiņās augstāk tiek inicializēts ar nulli, ternārais operators atgriezīs vērtību false. Šī nosacījuma dēļ cikla ķermenis tiks izpildīts tikai vienu reizi. Man šķiet, ka šis koda fragments darbojas pavisam citādāk, nekā iecerējis programmētājs.

Brīdinājums N6

Analizatora brīdinājums: V3022 [CWE-571] Izteiksme 'installedPackageVersions.Count != 1' vienmēr ir patiesa. NugetService.cs 1405

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

Šeit ir dīvains iemontēts nosacījums: installedPackageVersions.Count != 1, kas vienmēr būs true. Bieži šāds brīdinājums norāda uz loģisku kļūdu kodā, bet citos gadījumos tas vienkārši norāda uz lieku pārbaudi.

Brīdinājums N7

Analizatora brīdinājums: V3001 Bieži sastopami apakšizteikumi 'commandArguments.contains("-apikey")' ir gan pa kreisi, gan pa labi no operatora '||'. 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");
}

Programmētājs, kurš uzrakstījis šo koda daļu, nokopēja divas pēdējās rindiņas un aizmirsās tās rediģēt. Tādēļ Chocolatey lietotājiem tika izslēgta iespēja izmantot parametrus apikey vēl ar dažiem citiem veidiem. Līdzīgi iepriekš minētajiem parametriem, varu ieteikt šādus variantus:

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

Kopēšanas un ievietošanas kļūdas ir liela iespēja agrāk vai vēlāk parādīties jebkurā projektā ar lielu avota kodu daudzumu, un viens no labākajiem veidiem, kā ar tām cīnīties, ir statiskā analīze.

P.S. Un, kā vienmēr, šī kļūda bieži parādās daudzrindā nosacījuma beigās :). Skatiet publikāciju "Pēdējās rindiņas efekts".

Brīdinājums N8

Analizatora brīdinājums: V3095 [CWE-476] 'installedPackage' objekts tika izmantots pirms tā pārbaudīšanas pret nulli. Pārbaudiet rindas: 910, 917. NugetService.cs 910

public virtual ConcurrentDictionary 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)
  {
    ....
  }
  ....
}

Klasiskā kļūda: vispirms objekts installedPackage tiek izmantots, un pēc tam pārbauda uz null. Šī diagnostika norāda uz vienu no divām problēmām programmā: vai nu installedPackage nekad nav vienāds null, kas ir apšaubāms, un tad pārbaude ir lieka, vai mēs potenciāli varam iegūt nopietnu kļūdu kodā – mēģinājumu piekļūt nulles atsaucei.

Secinājums

Mēs esam veikuši vēl vienu mazu soli – tagad izmantot PVS-Studio ir kļuvusi vēl vienkāršāka un ērta. Tāpat vēlos teikt, ka Chocolatey ir labs pakotņu menedžeris ar niecīgiem koda trūkumiem, kurus varētu būt vēl mazāk, izmantojot PVS-Studio.

Aicinas lejupielādēt un izmēģināt PVS-Studio. Regulāra statiskā analizatora lietošana paaugstinās jūsu komandas izstrādātā koda kvalitāti un uzticamību un palīdzēs novērst daudzas nulles dienas ievainojamības.

P.S.

Pirms publikācijas mēs nosūtījām rakstu Chocolatey izstrādātājiem, un viņi to labi pieņēma. Neko kritisku mēs neatradām, taču viņiem, piemēram, patika mūsu atrasta kļūda, kas saistīta ar atslēgu „api-key”.

PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude no Azure DevOps

Ja vēlaties dalīties šajā rakstā ar angliski runājošo auditoriju, lūdzu, izmantojiet saiti uz tulkojumu: Vladislav Stolyarov. PVS-Studio tagad ir Chocolatey: Chocolatey pārbaude Azure DevOps ietvaros.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster