PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps
Continuiamo a rendere l'utilizzo di PVS-Studio più conveniente. Il nostro analizzatore è ora disponibile in Chocolatey, un gestore di pacchetti per Windows. Riteniamo che ciò faciliterà l'implementazione di PVS-Studio, in particolare, nei servizi cloud. Per non andare lontano, controlliamo il codice sorgente dello stesso Chocolatey. Azure DevOps fungerà da sistema CI.

Ecco un elenco degli altri nostri articoli sul tema dell'integrazione con i sistemi cloud:

Ti consiglio di prestare attenzione al primo articolo riguardante l'integrazione con Azure DevOps, poiché in questo caso alcuni punti vengono omessi per non essere duplicati.

Quindi, gli eroi di questo articolo:

Studio PVS è uno strumento di analisi statica del codice progettato per identificare errori e potenziali vulnerabilità nei programmi scritti in C, C++, C# e Java. Funziona su sistemi Windows, Linux e macOS a 64 bit e può analizzare il codice progettato per piattaforme ARM a 32 bit, 64 bit e integrate. Se è la prima volta che provi l'analisi statica del codice per controllare i tuoi progetti, ti consigliamo di familiarizzare con un articolo su come visualizzare rapidamente gli avvisi più interessanti di PVS-Studio e valutare le capacità di questo strumento.

Azure DevOps — un insieme di servizi cloud che coprono congiuntamente l'intero processo di sviluppo. Questa piattaforma include strumenti come Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, che consentono di accelerare il processo di creazione del software e migliorarne la qualità.

cioccolatoso è un gestore di pacchetti open source per Windows. L'obiettivo del progetto è automatizzare l'intero ciclo di vita del software dall'installazione all'aggiornamento e alla disinstallazione sui sistemi operativi Windows.

Informazioni sull'utilizzo di Chocolatey

Puoi vedere come installare il gestore pacchetti stesso qui collegamento. La documentazione completa per l'installazione dell'analizzatore è disponibile all'indirizzo collegamento Consulta la sezione Installazione utilizzando il gestore pacchetti Chocolatey. Ripeterò brevemente alcuni punti da lì.

Comando per installare l'ultima versione dell'analizzatore:

choco install pvs-studio

Comando per installare una versione specifica del pacchetto PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Per impostazione predefinita, è installato solo il nucleo dell'analizzatore, il componente Core. Tutti gli altri flag (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) possono essere passati utilizzando --package-parameters.

Un esempio di comando che installerà un analizzatore con un plug-in per Visual Studio 2019:

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

Consideriamo ora un esempio di utilizzo pratico dell'analizzatore in Azure DevOps.

registrazione

Lascia che ti ricordi che esiste una sezione separata su questioni come la registrazione di un account, la creazione di una pipeline di build e la sincronizzazione del tuo account con un progetto situato nel repository GitHub. articolo. Il nostro setup inizierà immediatamente con la scrittura di un file di configurazione.

Innanzitutto, impostiamo un trigger di avvio, indicando che verrà avviato solo in caso di modifiche Mastercard ramo:

trigger:
- master

Successivamente dobbiamo selezionare una macchina virtuale. Per ora sarà un agente ospitato da Microsoft con Windows Server 2019 e Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Passiamo al corpo del file di configurazione (block passi). Nonostante non sia possibile installare software arbitrario in una macchina virtuale, non ho aggiunto un contenitore Docker. Possiamo aggiungere Chocolatey come estensione per Azure DevOps. Per fare questo, andiamo a collegamento. Clic Ottienilo gratis. Successivamente, se sei già autorizzato, seleziona semplicemente il tuo account e, in caso contrario, fai la stessa cosa dopo l'autorizzazione.

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Qui devi selezionare dove aggiungeremo l'estensione e fare clic sul pulsante Installazione.

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Al termine dell'installazione, fare clic su Procedi all'organizzazione:

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Ora puoi vedere il modello per l'attività Chocolatey nella finestra task quando si modifica un file di configurazione azzurro-pipelines.yml:

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Fare clic su Chocolatey e visualizzare un elenco di campi:

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Qui dobbiamo selezionare install in campo con le squadre. IN Nome file Nuspec indicare il nome del pacchetto richiesto – pvs-studio. Se non specifichi la versione, verrà installata quella più recente, che per noi è completamente adatta. Premiamo il pulsante aggiungere e vedremo l'attività generata nel file di configurazione.

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

Successivamente, passiamo alla parte principale del nostro file:

- task: CmdLine@2
  inputs:
    script: 

Ora dobbiamo creare un file con la licenza dell'analizzatore. Qui NOMEPV и PVSKEY – nomi di variabili i cui valori specifichiamo nelle impostazioni. Memorizzeranno il login e la chiave di licenza di PVS-Studio. Per impostare i loro valori, aprire il menu Variabili->Nuova variabile. Creiamo le variabili NOMEPV per l'accesso e PVSKEY per la chiave dell'analizzatore. Non dimenticare di selezionare la casella Mantieni segreto questo valore per PVSKEY. Codice comando:

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

Costruiamo il progetto utilizzando il file bat situato nel repository:

сall build.bat

Creiamo una cartella in cui verranno archiviati i file con i risultati dell'analizzatore:

сall mkdir PVSTestResults

Iniziamo ad analizzare il progetto:

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

Convertiamo il nostro report in formato html utilizzando l'utilità PlogСonverter:

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

Ora devi creare un'attività in modo da poter caricare il report.

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

Il file di configurazione completo è simile al seguente:

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

Facciamo clic Salva->Salva->Esegui per eseguire l'attività. Scarichiamo il report accedendo alla scheda attività.

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Il progetto Chocolatey contiene solo 37615 righe di codice C#. Diamo un'occhiata ad alcuni degli errori riscontrati.

Risultati del test

Avvertimento N1

Avvertenza sull'analizzatore: V3005 La variabile 'Provider' viene assegnata a se stessa. CrytpoHashProviderSpecs.cs 38

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

L'analizzatore ha rilevato un'assegnazione della variabile a se stesso, il che non ha senso. Molto probabilmente, al posto di una di queste variabili ce ne dovrebbe essere un'altra. Bene, o questo è un errore di battitura e l'incarico extra può essere semplicemente rimosso.

Avvertimento N2

Avvertenza sull'analizzatore: V3093 [CWE-480] L'operatore '&' valuta entrambi gli operandi. Forse dovrebbe essere utilizzato invece un operatore di cortocircuito '&&'. Piattaforma.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;
  }
}

Differenza dell'operatore & dall'operatore && è quello se il lato sinistro dell'espressione è falso, verrà comunque calcolato il lato destro, il che in questo caso implica chiamate di metodo non necessarie system.directory_esiste.

Nel frammento considerato si tratta di un difetto minore. Sì, questa condizione può essere ottimizzata sostituendo l'operatore & con l'operatore &&, ma da un punto di vista pratico ciò non influisce su nulla. Tuttavia, in altri casi, la confusione tra & e && può causare seri problemi quando il lato destro dell'espressione viene trattato con valori errati/non validi. Ad esempio, nella nostra raccolta di errori, identificato utilizzando la diagnostica V3093, c'è questo caso:

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

Anche se l'indice k non è corretto, verrà utilizzato per accedere a un elemento dell'array. Di conseguenza, verrà generata un'eccezione IndexOutOfRangeException.

Avvertenze N3, N4

Avvertenza sull'analizzatore: V3022 [CWE-571] L'espressione 'shortPrompt' è sempre vera. InteractivePrompt.cs 101
Avvertenza sull'analizzatore: V3022 [CWE-571] L'espressione 'shortPrompt' è sempre 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
    ....
  }
  ....
}

In questo caso c'è una strana logica dietro il funzionamento dell'operatore ternario. Vediamo più nel dettaglio: se la condizione che ho contrassegnato con il numero 1 è soddisfatta, allora passeremo alla condizione 2, che è sempre vero, il che significa che verrà eseguita la riga 3. Se la condizione 1 risulta essere falsa, allora andremo alla riga contrassegnata con il numero 4, condizione in cui è sempre anche vero, il che significa che verrà eseguita la riga 5. Pertanto, le condizioni contrassegnate con il commento 0 non verranno mai soddisfatte, il che potrebbe non essere esattamente la logica di funzionamento che il programmatore si aspettava.

Avvertimento N5

Avvertenza sull'analizzatore: V3123 [CWE-783] Forse l'operatore '?:' funziona in modo diverso da quanto previsto. La sua priorità è inferiore a quella degli altri operatori nelle sue condizioni. Opzioni.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 diagnostica ha funzionato per la linea:

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

Poiché la variabile j poche righe sopra viene inizializzato a zero, l'operatore ternario restituirà il valore falso. A causa di questa condizione, il corpo del ciclo verrà eseguito una sola volta. Mi sembra che questo pezzo di codice non funzioni affatto come previsto dal programmatore.

Avvertimento N6

Avvertenza sull'analizzatore: V3022 [CWE-571] L'espressione 'installedPackageVersions.Count != 1' è sempre 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);
    }
    ....
  }
  ....
}

C'è una strana condizione nidificata qui: installatoPackageVersions.Count! = 1che sarà sempre vero. Spesso un avviso di questo tipo indica un errore logico nel codice e in altri casi indica semplicemente un controllo ridondante.

Avvertimento N7

Avvertenza sull'analizzatore: V3001 Sono presenti sottoespressioni identiche "commandArguments.contains("-apikey")" a sinistra e a destra di "||" operatore. 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");
}

Il programmatore che ha scritto questa sezione di codice ha copiato e incollato le ultime due righe e si è dimenticato di modificarle. Per questo motivo, gli utenti di Chocolatey non sono stati in grado di applicare il parametro apichia ancora un paio di modi. Analogamente ai parametri sopra, posso offrire le seguenti opzioni:

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

Gli errori di copia-incolla hanno un'alta probabilità di comparire prima o poi in qualsiasi progetto con una grande quantità di codice sorgente e uno dei migliori strumenti per combatterli è l'analisi statica.

PS E come sempre, questo errore tende ad apparire alla fine di una condizione su più righe :). Vedi pubblicazione "Effetto ultima riga".

Avvertimento N8

Avvertenza sull'analizzatore: V3095 [CWE-476] L'oggetto 'installedPackage' è stato utilizzato prima di essere verificato rispetto a null. Controllare le righe: 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)
  {
    ....
  }
  ....
}

Errore classico: prima l'oggetto pacchetto installato viene utilizzato e quindi controllato nullo. Questa diagnostica ci segnala uno dei due problemi del programma: o pacchetto installato mai uguale nullo, il che è dubbio, e quindi il controllo è ridondante, oppure potremmo potenzialmente ottenere un errore grave nel codice: un tentativo di accedere a un riferimento nullo.

conclusione

Quindi abbiamo fatto un altro piccolo passo: ora usare PVS-Studio è diventato ancora più semplice e conveniente. Vorrei anche dire che Chocolatey è un buon gestore di pacchetti con un numero limitato di errori nel codice, che potrebbero essere ancora inferiori utilizzando PVS-Studio.

Invitiamo scaricare e prova PVS-Studio. L'uso regolare di un analizzatore statico migliorerà la qualità e l'affidabilità del codice sviluppato dal tuo team e aiuterà a prevenirne molti vulnerabilità zero-day.

PS

Prima della pubblicazione, abbiamo inviato l'articolo agli sviluppatori di Chocolatey e lo hanno accolto bene. Non abbiamo trovato nulla di critico, ma a loro, ad esempio, è piaciuto il bug che abbiamo riscontrato relativo alla chiave “api-key”.

PVS-Studio è ora in Chocolatey: controlla Chocolatey da Azure DevOps

Se vuoi condividere questo articolo con un pubblico di lingua inglese, utilizza il link di traduzione: Vladislav Stolyarov. PVS-Studio è ora in Chocolatey: controllo di Chocolatey in Azure DevOps.

Fonte: habr.com

Aggiungi un commento