PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps
Ne vazhdojmë ta bëjmë përdorimin e PVS-Studio më të lehtë. Tani analizuese jonë është e disponueshme në Chocolatey, menaxhuesin e paketave për Windows. Mendojmë se kjo do të lehtësojë vendosjen e PVS-Studio, veçanërisht në shërbimet cloud. Për të mos shkuar shumë larg, le të kontrollojmë kodin burimor të të njëjtit Chocolatey. Si sistem CI do të përdorim Azure DevOps.

Ja lista e artikujve tanë të tjerë mbi integrimin me sistemet cloud:

Këshilloj që të kushtoni vëmendje artikullit të parë rreth integrimit me Azure DevOps, pasi në këtë rast disa momente janë lënë mënjanë për të mos u përsëritur.

Pra, heronjtë e këtij artikulli janë:

PVS-Studio — një mjet analize statike të kodit, i destinuar për identifikimin e gabimeve dhe vulnerabiliteteve potenciale në programet e shkruara në gjuhët C, C++, C# dhe Java. Funksionon në sisteme 64-bit në Windows, Linux dhe macOS, dhe mund të analizojë kodin që është menduar për platformat 32-bit, 64-bit dhe ARM të integruara. Nëse po provoni për herë të parë analizën statike të kodit për të kontrolluar projektet tuaja, ju rekomandojmë të jeni të njohur me artikullin rreth mënyrës për të parë shpejt paralajmërimet më interesante PVS-Studio dhe për të vlerësuar mundësitë e këtij mjeti.

Azure DevOps — një grup shërbesh cloud që mbulojnë të gjithë procesin e zhvillimit. Ky platformë përfshin mjete si Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, që ndihmojnë në përshpejtimin e procesit të krijimit të softuerit dhe përmirësimin e cilësisë së tij.

Chocolatey – një menaxhues pakete për Windows me burim të hapur. Qëllimi i projektit është të automatizojë të gjithë ciklin e jetës së softuerit nga instalimi deri te përditësimi dhe fshirja në sistemet operative Windows.

Rreth përdorimit të Chocolatey

Të shihni se si të instaloni vetë menaxhuesin e paketave, mund ta gjeni në këtë linkun. Dokumentacioni i plotë për instalimin e analizuese është i disponueshëm në linkun në seksionin "Instalimi duke përdorur menaxhuesin e paketave Chocolatey". Në mënyrë të përmbledhur, do të përsëris disa pika nga aty.

Komanda për instalimin e versionit më të fundit të analizuese:

choco install pvs-studio

Komanda për instalimin e një versioni specifik të paketës PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Default installs only the core of the analyzer — the Core component. All other flags (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) can be passed with —package-parameters.

Example command to install the analyzer with the plugin for Visual Studio 2019:

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

Now let's look at a convenient example of using the analyzer with Azure DevOps.

Configuration

I remind you that there are separate instructions on such matters as account registration, creating a Build Pipeline, and syncing the account with a project in the GitHub repository. artikulliOur setup will start right away with writing the configuration file.

First, let's set up the trigger for execution, specifying that we only trigger for changes in master the branch:

trigger:
- master

Next, we need to choose a virtual machine. For now, it will be a Microsoft-hosted agent with Windows Server 2019 and Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Let's move to the body of the configuration file (block steps). Despite the fact that arbitrary software cannot be installed on the virtual machine, I decided not to add a Docker container. We can add Chocolatey as an extension for Azure DevOps. For this, we can go to linkun. Click Get it free. Then, if you are already logged in, just select your account, or if not, do the same after logging in.

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Here you need to select where we will add the extension and click the button Install.

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

After successful installation, click Proceed to organization:

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Now you can see the template for the Chocolatey task in the window tasks when editing the configuration file azure-pipelines.yml:

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Click on Chocolatey and see the list of fields:

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Here we need to select instalo in the commands field. In Nuspec File Name we will specify the name of the desired package – pvs-studio. If no version is specified, the latest version will be installed, which suits us perfectly. Click on the button add and see the generated task in the configuration file.

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

Next, let's move on to the main part of our file:

- task: CmdLine@2
  inputs:
    script: 

Now we need to create a file with the license for the analyzer. Here PVSNAME dhe PVSKEY – are the names of the variables whose values we specify in the settings. They will store the username and license key for PVS-Studio. To set their values, we will open the menu Variables->New variable. We will create variables PVSNAME for the login and PVSKEY për çelësin e analizuesit. Mos harro të vendosësh shenjën e kontrollit Mbaje këtë vlerë sekrete për PVSKEY. Kodi i komandës:

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

Do të mbledhim projektin me ndihmën e skedarit bat, që ndodhet në depo:

thirr build.bat

Do të krijojmë një dosje ku do të ruhen skedarët me rezultatet e punës së analizuesit:

thirr mkdir PVSTestResults

Do të fillojmë analizën e projektit:

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

Do ta konvertojmë raportin tonë në format html me ndihmën e utilitarit PlogConverter:

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

Tani duhet të krijojmë një detyrë që të mund të nxjerrim raportin.

- detyrë: PublishBuildArtifacts@1
  hyrjet:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    kushti: always()

I gjithë skedari i konfigurimit duket kështu:

trigger:
- master

pool:
  vmImage: 'windows-latest'

steps:
- detyrë: ChocolateyCommand@0
  hyrjet:
    komandë: 'instalo'
    installPackageId: 'pvs-studio'

- detyrë: CmdLine@2
  hyrjet:
    skript: |
      thirr "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      credentials –u $(PVSNAME) –n $(PVSKEY)
      thirr build.bat
      thirr mkdir PVSTestResults
      thirr "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
      –t .srcchocolatey.sln –o .PVSTestResultsChoco.plog
      thirr "C:Program Files (x86)PVS-StudioPlogConverter.exe" 
      –t html –o .PVSTestResults .PVSTestResultsChoco.plog

- detyrë: PublishBuildArtifacts@1
  hyrjet:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    kushti: always()

Të klikojmë Ruaj->Ruaj->Ekzekuto për të filluar detyrën. Do të nxjerrim raportin duke hyrë në skedën e detyrës.

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Projekti Chocolatey ka gjithsej 37615 rreshta kodi C#. Le të shqyrtojmë disa nga gabimet e gjetura.

Rezultatet e kontrollit

Kujdesi N1

Kujdesi i analizuesit: V3005 Variabla ‘Provider’ i caktohet vetë. CrytpoHashProviderSpecs.cs 38

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

Analizuesi gjeti përjashtimin e variablës me veten e saj, që nuk ka kuptim. Ndoshta në vend të një prej këtyre variablave duhet të jetë ndonjë tjetër. Ose ndoshta është një gabim shtypi, dhe caktoja të tepërt mund të hiqet thjesht.

Kujdesi N2

Kujdesi i analizuesit: V3093 [CWE-480] Operatorët ‘&’ vlerësojnë të dy operandët. Ndoshta duhet të përdoret operatori i shkurtër ‘&&’ në vend.

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;
  }
}

Dallimi i operatorit & nga operatori && ka në lidhje me faktin që nëse pjesa e majtë e shprehjes — false, do të llogaritet gjithsesi pjesa e djathtë, e cila në këtë rast përfshin thirrje të tepruara të metodës system.directory_exists.

Në fragmentin e shqyrtuar, ky është një gabim i vogël. Po, kjo kusht shumë mirë mund të optizohet duke zëvendësuar operatorin & me operatorin &&, por, nga pikëpamja praktike, kjo nuk ndikon në asgjë. Megjithatë, në raste të tjera, konfuzioni midis & dhe && mund të shkaktojë probleme serioze, kur pjesa e djathtë e shprehjes punon me vlera të pasakta / të pavlefshme. Për shembull, në koleksionin tonë të gabimeve, të identifikuara përmes diagnostikimit V3093, ka një rast të tillë:

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

Edhe nëse indeksi k është i pasaktë, ai do të përdoret për të aksesuar elementin e array-it. Si rezultat, do të gjenerohet një përjashtim IndexOutOfRangeException.

Kujdeset N3, N4

Kujdesi i analizuesit: V3022 [CWE-571] Shprehja ‘shortPrompt’ është gjithmonë e vërtetë. InteractivePrompt.cs 101
Kujdesi i analizuesit: V3022 [CWE-571] Shprehja ‘shortPrompt’ është gjithmonë e vërtetë. 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
    ....
  }
  ....
}

Në këtë rast ka një logjikë të çuditshme të funksionimit të operatorit ternar. Le të shqyrtojmë më në detaje: nëse kushti i shënuar nga unë me numrin 1 përmbushet, atëherë do të kalojmë te kushti 2, i cili gjithmonë true, që do të thotë se do të ekzekutohet rreshti 3. Nëse kushti 1 del të jetë i pavërtetë, atëherë do të kalojmë tek rreshti i shënuar me numrin 4, kushti në të cilin gjithashtu gjithmonë true, që do të thotë, do të ekzekutohet rreshti 5. Kështu, kushtet e shënuara me komentin 0, kurrë nuk do të përmbushen, që mund të jetë një logjikë që programuesi nuk e priste.

Kujdesi N5

Kujdesi i analizuesit: V3123 [CWE-783] Ndoshta operatori ‘?:’ funksionon ndryshe nga sa pritej. Prioriteti i tij është më i ulët se prioriteti i operatorëve të tjerë në kushtin e tij. 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 ? "VLERË" : "VLERË" + (index + 1);
  }
}

Diagnostika u aktivizua për rreshtin:

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

Duke pasur parasysh se variabli j është inicializuar me zero disa rreshta më sipër, operatori ternar do të kthejë vlerën false. Për shkak të kësaj kushtet, trupi i ciklit do të ekzekutohet vetëm një herë. Më duket se ky fragment kodi funksionon ndryshe nga sa e kishte menduar programuesi.

Alarmi N6

Kujdesi i analizuesit: V3022 [CWE-571] Shprehja ‘installedPackageVersions.Count != 1’ është gjithmonë e vërtetë. NugetService.cs 1405

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

Këtu ka një kusht të çuditshëm të ndërlidhur: installedPackageVersions.Count != 1, i cili do të jetë gjithmonë true. Shpesh ky lloj paralajmërimi tregon për një gabim logjik në kod, dhe në rastet e tjera thjesht për një kontroll të panevojshëm.

Alarmi N7

Kujdesi i analizuesit: V3001 Ekzistojnë shprehje identike sub në të majtë dhe në të djathtë të operatorit ‘||’. 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");
}

Programuesi që shkroi këtë pjesë kodi, e kopjoi dy rreshtat e fundit dhe harroi t'i redaktojë ato. Për këtë arsye, përdoruesit e Chocolatey u privuan nga mundësia për të aplikuar parametrin apikey me disa mënyra të tjera. Njësoj si parametrat e sipërm, mund të sugjeroj këto opsione:

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

Gabimet e kopjimit dhe ngjitjes kanë një mundësi të madhe që të shfaqen shpejt në çdo projekt me një sasi të madhe të kodit burim, dhe një prej mjeteve më të mira për t'u luftuar me to është analiza statike.

P.S. Dhe si gjithmonë, kjo gabim ka tendencë të shfaqet në fund të një kushti shumë-rreshtëshe :). Shihni publikimin "Efekti i rreshtit të fundit".

Alarmi N8

Kujdesi i analizuesit: V3095 [CWE-476] Objeksioni ‘installedPackage’ u përdor para se të verifikohej me null. Kontrolloni rreshtat: 910, 917. NugetService.cs 910

publike virtuale 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)
  {
    ....
  }
  ....
}

Gabimi klasik: objekti përdoret në fillim installedPackage dhe më pas kontrollohet për null. Ky diagnostikim na tregon për një nga dy problemet në program: ose installedPackage nuk është kurrë e barabartë me null, që është dyshim, dhe atëherë kontrolli është i tepërt, ose potencialisht mund të marrim një gabim të rëndë në kod – një përpjekje për qasje me referencë zero.

Përfundim

Kemi bërë edhe një hap të vogël – tani përdorimi i PVS-Studio është bërë edhe më i lehtë dhe më i përshtatshëm. Po ashtu, dua të them se Chocolatey është një menaxher i mirë paketash me një numër të vogël gabimesh në kod, që do të mund të ishin edhe më të pakta me përdorimin e PVS-Studio.

Ftojmë shkarkoni dhe të provoni PVS-Studio. Përdorimi i rregullt i analizatorit statik do të rrisë cilësinë dhe besueshmërinë e kodit që ekipi juaj zhvillon dhe do të ndihmojë në parandalimin e shumë shfrytëzimeve të zero ditëve.

P.S.

Para publikimit, e dërguam artikullin zhvilluesve të Chocolatey, dhe ata e pranuan mirë. Asgjë kritike nuk u gjet nga ne, por atyre, për shembull, iu pëlqeu gabimi që e gjetëm lidhur me çelësin "api-key".

PVS-Studio tani në Chocolatey: kontrolli i Chocolatey nga Azure DevOps

Nëse dëshironi të ndani këtë artikull me audiencën anglisht-folëse, ju lutem përdorni lidhjen për përkthimin: Vladislav Stolyarov. PVS-Studio tani është në Chocolatey: Kontrollimi i Chocolatey nën Azure DevOps.

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster