PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps
Ni daŭre igas uzadon de PVS-Studio pli oportuna. Nia analizilo nun haveblas en Chocolatey, pakaĵmanaĝero por Vindozo. Ni kredas, ke ĉi tio faciligos la disfaldiĝon de PVS-Studio, precipe en nubaj servoj. Por ne iri malproksimen, ni kontrolu la fontkodon de la sama Chocolatey. Azure DevOps funkcios kiel CI-sistemo.

Jen listo de niaj aliaj artikoloj pri la temo de integriĝo kun nubaj sistemoj:

Mi konsilas vin atenti la unuan artikolon pri integriĝo kun Azure DevOps, ĉar ĉi-kaze iuj punktoj estas preterlasitaj por ne duobliĝi.

Do, la herooj de ĉi tiu artikolo:

PVS Studio estas senmova koda analizilo dizajnita por identigi erarojn kaj eblajn vundeblecojn en programoj skribitaj en C, C++, C# kaj Java. Funkcias sur 64-bitaj Vindozo, Linukso kaj macOS-sistemoj, kaj povas analizi kodon desegnitan por 32-bita, 64-bita kaj enigita ARM-platformoj. Se ĉi tio estas via unua fojo, kiam vi provas statikan kodan analizon por kontroli viajn projektojn, ni rekomendas, ke vi konatiĝu artikolo pri kiel rapide vidi la plej interesajn avertojn de PVS-Studio kaj taksi la kapablojn de ĉi tiu ilo.

Azure DevOps — aro da nubaj servoj, kiuj kune kovras la tutan disvolvan procezon. Ĉi tiu platformo inkluzivas ilojn kiel Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, kiuj permesas vin akceli la procezon de kreado de programaro kaj plibonigi ĝian kvaliton.

Ĉokolado estas malfermfonta pakaĵmanaĝero por Vindozo. La celo de la projekto estas aŭtomatigi la tutan programaron vivociklon de instalado ĝis ĝisdatigo kaj malinstalo sur Vindozaj operaciumoj.

Pri uzado de Chocolatey

Vi povas vidi kiel instali la pakaĵmanaĝeron mem ĉe ĉi tio ligilo. Kompleta dokumentaro por instali la analizilon haveblas ĉe ligilo Vidu la Instaladon uzante la sekcion pri pakaĵa administranto de Chocolatey. Mi mallonge ripetos kelkajn punktojn de tie.

Komando instali la lastan version de la analizilo:

choco install pvs-studio

Komando instali specifan version de la pako PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Defaŭlte, nur la kerno de la analizilo, la Kerna komponanto, estas instalita. Ĉiuj aliaj flagoj (Memstara, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) povas esti pasitaj uzante --package-parameters.

Ekzemplo de komando, kiu instalos analizilon kun kromaĵo por Visual Studio 2019:

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

Nun ni rigardu ekzemplon de oportuna uzo de la analizilo sub Azure DevOps.

alĝustigo

Mi memorigu vin, ke ekzistas aparta sekcio pri tiaj aferoj kiel registri konton, krei Konstrui Pipeline kaj sinkronigi vian konton kun projekto situanta en la deponejo de GitHub. artikolo. Nia aranĝo tuj komencos skribante agordan dosieron.

Unue, ni agordu lanĉan ellasilon, indikante, ke ni lanĉas nur por ŝanĝoj en majstro branĉo:

trigger:
- master

Poste ni devas elekti virtualan maŝinon. Nuntempe ĝi estos agento gastigita de Mikrosofto kun Windows Server 2019 kaj Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Ni transiru al la korpo de la agorda dosiero (bloko paŝoj). Malgraŭ tio, ke vi ne povas instali arbitran programaron en virtualan maŝinon, mi ne aldonis Docker-ujon. Ni povas aldoni Chocolatey kiel etendon por Azure DevOps. Por fari tion, ni iru al ligilo. Klaku Akiru ĝin senpage. Poste, se vi jam estas rajtigita, simple elektu vian konton, kaj se ne, tiam faru la samon post rajtigo.

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Ĉi tie vi devas elekti kie ni aldonos la etendon kaj alklaku la butonon instali.

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Post sukcesa instalado, alklaku Iru al organizo:

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Vi nun povas vidi la ŝablonon por la tasko Chocolatey en la fenestro taskoj dum redaktado de agorda dosiero azure-pipelines.yml:

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Klaku sur Chocolatey kaj vidu liston de kampoj:

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Ĉi tie ni devas elekti instali en la kampo kun la teamoj. EN Nuspec Dosiernomo indiku la nomon de la bezonata pako - pvs-studio. Se vi ne specifas la version, la plej nova estos instalita, kiu tute konvenas al ni. Ni premu la butonon aldoni kaj ni vidos la generitan taskon en la agorda dosiero.

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

Poste, ni transiru al la ĉefa parto de nia dosiero:

- task: CmdLine@2
  inputs:
    script: 

Nun ni devas krei dosieron kun la analizilo-licenco. Jen PVSNAME и PVSKEY - nomoj de variabloj, kies valorojn ni specifas en la agordoj. Ili stokos la ensaluton kaj permesilon ŝlosilon de PVS-Studio. Por agordi iliajn valorojn, malfermu la menuon Variabloj-> Nova variablo. Ni kreu variablojn PVSNAME por ensaluto kaj PVSKEY por la analizilo-ŝlosilo. Ne forgesu marki la skatolon Konservu ĉi tiun valoron sekreta por PVSKEY. Kodo de komando:

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

Ni konstruu la projekton uzante la bat-dosieron situantan en la deponejo:

сall build.bat

Ni kreu dosierujon, kie estos konservitaj dosieroj kun la rezultoj de la analizilo:

сall mkdir PVSTestResults

Ni komencu analizi la projekton:

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

Ni konvertas nian raporton al html-formato uzante la ilon PlogСonverter:

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

Nun vi devas krei taskon por ke vi povu alŝuti la raporton.

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

La kompleta agorda dosiero aspektas jene:

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

Ni klaku Konservi-> Konservi-> Run por ekzekuti la taskon. Ni elŝutu la raporton irante al la langeto de taskoj.

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

La projekto Chocolatey enhavas nur 37615 liniojn de C#-kodo. Ni rigardu kelkajn el la trovitaj eraroj.

Testrezultoj

Averto N1

Averto de analizilo: V3005 La 'Proviganto' variablo estas asignita al si mem. CrytpoHashProviderSpecs.cs 38

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

La analizilo detektis taskon de la variablo al si mem, kio ne havas sencon. Plej verŝajne, anstataŭ unu el ĉi tiuj variabloj devus esti iu alia. Nu, aŭ ĉi tio estas tajperaro, kaj la kroma tasko simple povas esti forigita.

Averto N2

Averto de analizilo: V3093 [CWE-480] La '&' funkciigisto taksas ambaŭ operantojn. Eble oni uzu anstataŭe kurtcirkvitan '&&'. 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;
  }
}

Operaciisto diferenco & de la funkciigisto && estas ke se la maldekstra flanko de la esprimo estas falsa, tiam la dekstra flanko ankoraŭ estos kalkulita, kio ĉi-kaze implicas nenecesajn metodovokojn sistemo.dosierujo_ekzistas.

En la pripensita fragmento, ĉi tio estas negrava difekto. Jes, ĉi tiu kondiĉo povas esti optimumigita per anstataŭigo de la & operatoro per la && operatoro, sed el praktika vidpunkto, tio ne influas ion ajn. Tamen, en aliaj kazoj, konfuzo inter & kaj && povas kaŭzi gravajn problemojn kiam la dekstra flanko de la esprimo estas traktita kun malĝustaj/nevalidaj valoroj. Ekzemple, en nia erarkolekto, identigite per la V3093-diagnozo, estas ĉi tiu kazo:

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

Eĉ se la indekso k estas malĝusta, ĝi estos uzata por aliri tabelelementon. Kiel rezulto, escepto estos ĵetita IndexOutOfRangeException.

Avertoj N3, N4

Averto de analizilo: V3022 [CWE-571] Esprimo 'shortPrompt' ĉiam estas vera. InteractivePrompt.cs 101
Averto de analizilo: V3022 [CWE-571] Esprimo 'shortPrompt' ĉiam estas vera. 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
    ....
  }
  ....
}

En ĉi tiu kazo, estas stranga logiko malantaŭ la operacio de la ternara operatoro. Ni rigardu pli detale: se la kondiĉo, kiun mi markis per numero 1, estas plenumita, tiam ni transiros al kondiĉo 2, kiu ĉiam estas veraj, kio signifas, ke estos ekzekutita linio 3. Se kondiĉo 1 montriĝas malvera, tiam ni iros al la linio markita per numero 4, la kondiĉo en kiu estas ankaŭ ĉiam. veraj, kio signifas ke estos ekzekutita linio 5. Tiel, la kondiĉoj markitaj per komento 0 neniam estos plenumitaj, kio eble ne estas ĝuste la logiko de operacio kiun la programisto atendis.

Averto N5

Averto de analizilo: V3123 [CWE-783] Eble la operatoro '?:' funkcias alimaniere ol ĝi estis atendita. Ĝia prioritato estas pli malalta ol prioritato de aliaj funkciigistoj en sia kondiĉo. Opcioj.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);
  }
}

La diagnozo funkciis por la linio:

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

Ekde la variablo j kelkaj linioj supre estas pravigitaj al nulo, la ternara operatoro redonos la valoron falsa. Pro ĉi tiu kondiĉo, la korpo de la buklo estos ekzekutita nur unufoje. Ŝajnas al mi, ke ĉi tiu kodo tute ne funkcias kiel la programisto intencis.

Averto N6

Averto de analizilo: V3022 [CWE-571] Esprimo 'installedPackageVersions.Count != 1' ĉiam estas vera. 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);
    }
    ....
  }
  ....
}

Estas stranga nesta kondiĉo ĉi tie: installPackageVersions.Count != 1kiu ĉiam estos veraj. Ofte tia averto indikas logikan eraron en la kodo, kaj en aliaj kazoj ĝi simple indikas redundan kontrolon.

Averto N7

Averto de analizilo: V3001 Estas identaj subesprimoj 'commandArguments.contains("-apikey")' maldekstre kaj dekstre de la '||' operatoro. 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");
}

La programisto kiu skribis ĉi tiun sekcion de kodo kopiis kaj algluis la lastajn du liniojn kaj forgesis redakti ilin. Pro tio, Chocolatey-uzantoj ne povis apliki la parametron apikey kelkajn pliajn manierojn. Simile al la parametroj supre, mi povas proponi la jenajn eblojn:

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

Kopi-algluaj eraroj havas altan ŝancon aperi frue aŭ malfrue en iu ajn projekto kun granda kvanto da fontkodo, kaj unu el la plej bonaj iloj por kontraŭbatali ilin estas statika analizo.

PS Kaj kiel ĉiam, ĉi tiu eraro emas aperi ĉe la fino de plurlinia kondiĉo :). Vidu publikigon "Lasta linio-efiko".

Averto N8

Averto de analizilo: V3095 [CWE-476] La objekto 'installedPackage' estis uzata antaŭ ol ĝi estis kontrolita kontraŭ nulo. Kontrolu liniojn: 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)
  {
    ....
  }
  ....
}

Klasika eraro: objekto unue instalita Pako estas uzata kaj poste kontrolita null. Ĉi tiu diagnozo rakontas al ni pri unu el du problemoj en la programo: ĉu instalita Pako neniam egala null, kio estas dubinda, kaj tiam la ĉeko estas superflua, aŭ ni eble povus ricevi gravan eraron en la kodo - provo aliri nulan referencon.

konkludo

Do ni faris alian malgrandan paŝon - nun uzi PVS-Studio fariĝis eĉ pli facila kaj pli oportuna. Mi ankaŭ ŝatus diri, ke Chocolatey estas bona pakaĵmanaĝero kun malgranda nombro da eraroj en la kodo, kiuj povus esti eĉ pli malmultaj kiam oni uzas PVS-Studio.

Ni invitas vin скачать kaj provu PVS-Studio. Regula uzo de senmova analizilo plibonigos la kvaliton kaj fidindecon de la kodo disvolvata de via teamo kaj helpos malhelpi multajn nultagaj vundeblecoj.

PS

Antaŭ publikigo, ni sendis la artikolon al la Chocolatey-programistoj, kaj ili bone ricevis ĝin. Ni trovis nenion kritikan, sed ili, ekzemple, ŝatis la cimon, kiun ni trovis rilata al la ŝlosilo "api-key".

PVS-Studio nun estas en Chocolatey: kontrolanta Chocolatey de sub Azure DevOps

Se vi volas dividi ĉi tiun artikolon kun anglalingva publiko, bonvolu uzi la tradukan ligilon: Vladislav Stolyarov. PVS-Studio Nun Estas en Chocolatey: Kontrolante Chocolatey sub Azure DevOps.

fonto: www.habr.com

Aldoni komenton