PVS-Studio ist jetzt in Chocolatey: Chocolatey von Azure DevOps überprüfen

Figur 4

Wir machen die Verwendung von PVS-Studio weiterhin komfortabler. Unser Analysegerät ist jetzt in Chocolatey, dem Paketmanager für Windows, verfügbar. Wir glauben, dass dies die Bereitstellung von PVS-Studio insbesondere in Cloud-Diensten erleichtern wird. Um nicht weit zu kommen, überprüfen Sie den Quellcode des gleichen Chocolatey. Das CI-System ist Azure DevOps.

Hier ist eine Liste unserer anderen Artikel zur Cloud-Integration:


Ich empfehle Ihnen, den ersten Artikel über die Integration in Azure DevOps zu lesen, da in diesem Fall einige Punkte weggelassen werden, um nicht dupliziert zu werden.

Die Helden dieses Artikels:

PVS-Studio ist ein statisches Code-Analyse-Tool, mit dem Fehler und potenzielle Schwachstellen in Programmen erkannt werden können, die in C, C ++, C # und Java geschrieben wurden. Es funktioniert auf 64-Bit-Systemen unter Windows, Linux und macOS und kann Code analysieren, der für 32-Bit-, 64-Bit- und eingebettete ARM-Plattformen entwickelt wurde. Wenn Sie zum ersten Mal eine statische Code-Analyse durchführen, um Ihre Projekte zu überprüfen, empfehlen wir Ihnen, den Artikel zu lesen, in dem erläutert wird, wie Sie die interessantesten PVS-Studio-Warnungen schnell anzeigen und die Funktionen dieses Tools bewerten können.

Azure DevOps- Eine Reihe von Cloud-Diensten, die gemeinsam den gesamten Entwicklungsprozess abdecken. Die Plattform enthält Tools wie Azure-Pipelines, Azure-Boards, Azure-Artefakte, Azure-Repos und Azure-Testpläne, die den Prozess der Softwareerstellung beschleunigen und deren Qualität verbessern.

Chocolatey ist ein Open Source-Paketmanager für Windows. Ziel des Projekts ist es, den gesamten Software-Lebenszyklus von der Installation bis zur Aktualisierung und Deinstallation unter Windows-Betriebssystemen zu automatisieren.

Über die Verwendung von Chocolatey


Über diesen Link können Sie sehen, wie Sie den Paketmanager installieren . Die vollständige Dokumentation zur Installation des Analysegeräts finden Sie unter dem Link im Abschnitt „Installation mit dem Chocolatey-Paketmanager“. Ich werde einige Punkte von dort kurz wiederholen.

Befehl zum Installieren der neuesten Analyseversion:

choco install pvs-studio

Der Befehl zum Installieren einer bestimmten Version des PVS-Studio-Pakets:

choco install pvs-studio --version=7.05.35617.2075

Standardmäßig ist nur der Analysatorkern installiert - die Kernkomponente. Alle anderen Flags (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) können mit --package-Parametern übergeben werden.

Ein Beispiel für einen Befehl, mit dem der Analysator mit einem Plug-In für Visual Studio 2019 installiert wird:

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

Schauen wir uns nun ein Beispiel für die bequeme Verwendung des Analysators unter Azure DevOps an.

Anpassung


Ich erinnere Sie daran, dass es einen separaten Artikel zu Themen wie dem Registrieren eines Kontos, dem Erstellen einer Build-Pipeline und dem Synchronisieren eines Kontos mit einem Projekt im Repository auf GitHub gibt . Unser Setup beginnt sofort mit dem Schreiben einer Konfigurationsdatei.

Konfigurieren Sie zunächst den Trigger Trigger, was darauf hinweist , dass wir nur für Änderungen im Laufe Master Zweig:

trigger:
- master

Als nächstes müssen wir eine virtuelle Maschine auswählen. Derzeit handelt es sich um einen von Microsoft gehosteten Agenten mit Windows Server 2019 und Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Fahren wir mit dem Hauptteil der Konfigurationsdatei fort ( Schrittblock ). Trotz der Tatsache, dass keine beliebige Software in einer virtuellen Maschine installiert werden kann, habe ich keinen Docker-Container hinzugefügt. Wir können Chocolatey als Erweiterung für Azure DevOps hinzufügen. Klicken Sie dazu auf den Link . Klicken Sie auf Get it free . Wenn Sie bereits autorisiert sind, wählen Sie einfach Ihr Konto aus. Wenn nicht, machen Sie dasselbe nach der Autorisierung.

Figur 2


Hier müssen Sie auswählen, wo wir die Erweiterung hinzufügen möchten, und auf die Schaltfläche Installieren klicken .

Abbildung 5


Klicken Sie nach einer erfolgreichen Installation auf Zur Organisation fortfahren :

Abbildung 9


Jetzt können Sie die Vorlage für die Chocolatey-Aufgabe im Aufgabenfenster sehen, wenn Sie die Konfigurationsdatei azure-pipelines.yml bearbeiten :

Abbildung 6


Klicken Sie auf Chocolatey und sehen Sie eine Liste der Felder:

Abbildung 7


Hier müssen wir im Befehlsfeld installieren auswählen . In Nuspec Dateiname, geben Sie den Namen des gewünschten Paket - PVS-Studio. Wenn Sie keine Version angeben, wird diese installiert, was für uns völlig passend ist. Klicken Sie auf die Schaltfläche Hinzufügen und sehen Sie die gebildete Aufgabe in der Konfigurationsdatei.

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

Als nächstes gehen wir zum Hauptteil unserer Datei über:

- task: CmdLine@2
  inputs:
    script: 

Jetzt müssen wir eine Datei mit der Analysatorlizenz erstellen. Hier sind PVSNAME und PVSKEY die Namen der Variablen, deren Werte wir in den Einstellungen angeben. Sie speichern den PVS-Studio-Login und den Lizenzschlüssel. Öffnen Sie zum Einstellen der Werte das Menü Variablen-> Neue Variable . Erstellen Sie die PVSNAME- Variablen für die Anmeldung und PVSKEY für den Analysatorschlüssel. Denken Sie daran, das Kontrollkästchen Diesen Wert geheim halten für PVSKEY zu aktivieren . Teamcode:

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

Lassen Sie uns das Projekt mit der im Repository liegenden bat-Datei erstellen:

all build.bat

Erstellen Sie einen Ordner, in dem die Dateien mit den Ergebnissen der Analysatorarbeit liegen:

all mkdir PVSTestResults

Führen Sie die Projektanalyse aus:

all "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
–t .\src\chocolatey.sln –o .\PVSTestResults\Choco.plog 

Wir konvertieren unseren Bericht mit dem Dienstprogramm Plogonverter in das HTML-Format:

all "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" 
–t html –o \PVSTestResults\ .\PVSTestResults\Choco.plog

Jetzt müssen Sie eine Aufgabe erstellen, damit Sie den Bericht hochladen können.

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

Die vollständige Konfigurationsdatei sieht folgendermaßen aus:

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-Studio\PVS-Studio_Cmd.exe" 
      credentials –u $(PVSNAME) –n $(PVSKEY)
      call build.bat
      call mkdir PVSTestResults
      call "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
      –t .\src\chocolatey.sln –o .\PVSTestResults\Choco.plog
      call "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" 
      –t html –o .\PVSTestResults\ .\PVSTestResults\Choco.plog

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

Klicken Sie auf Speichern-> Speichern-> Ausführen , um die Aufgabe zu starten. Entladen Sie den Bericht, indem Sie zur Registerkarte Aufgabe wechseln.

Abbildung 8



Das Chocolatey-Projekt enthält insgesamt 37.615 Zeilen C # -Code. Betrachten Sie einige der gefundenen Fehler.

Validierungsergebnisse


Warnung N1

Analyzer Warnung: V3005 Die Variable 'Provider' wird sich selbst zugewiesen. CrytpoHashProviderSpecs.cs 38

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

Der Analysator hat die Zuordnung einer Variablen zu sich selbst gefunden, was nicht sinnvoll ist. Am wahrscheinlichsten sollte anstelle einer dieser Variablen eine andere sein. Nun, oder dies ist ein Tippfehler, und unnötige Zuweisungen können einfach gelöscht werden.

Warnung N2

Analyzer Warnung: V3093 [CWE-480] Der Operator '&' wertet beide Operanden aus. Möglicherweise sollte stattdessen ein Kurzschlussoperator "&&" verwendet werden. 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;
  }
}

Der Unterschied zwischen dem Operator & und dem Operator && besteht darin, dass, wenn die linke Seite des Ausdrucks falsch ist , die rechte Seite trotzdem berechnet wird, was in diesem Fall zusätzliche Aufrufe der Methode system.directory_exists impliziert .

In diesem Fragment ist dies ein kleiner Fehler. Ja, diese Bedingung kann optimiert werden, indem der Operator & durch den Operator && ersetzt wird. Aus praktischer Sicht hat dies jedoch keine Auswirkungen. In anderen Fällen kann eine Verwechslung zwischen & und && jedoch zu ernsthaften Problemen führen, wenn die rechte Seite des Ausdrucks mit falschen / ungültigen Werten arbeitet. In unserer Sammlung von Fehlern, die von der V3093-Diagnose erkannt wurden , gibt es beispielsweise einen solchen Fall:

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

Selbst wenn der Index k falsch ist, wird er verwendet, um auf das Array-Element zuzugreifen. Infolgedessen wird eine IndexOutOfRangeException ausgelöst .

Warnungen N3, N4

Analyzer Warnung: V3022 [CWE-571] Der Ausdruck 'shortPrompt' ist immer wahr. InteractivePrompt.cs 101
Analyzer Warnung: V3022 [CWE-571] Der Ausdruck 'shortPrompt' ist immer wahr. 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 diesem Fall gibt es eine seltsame Logik des ternären Operators. Schauen wir uns das genauer an: Wenn die mit Nummer 1 gekennzeichnete Bedingung erfüllt ist, gehen wir zu Bedingung 2, die immer wahr ist , was bedeutet, dass Zeile 3 erfüllt ist. Wenn sich herausstellt, dass Bedingung 1 falsch ist, gehen wir zu der mit Nummer 4 gekennzeichneten Bedingung, in der auch Immer wahr , was bedeutet, dass Zeile 5 ausgeführt wird. Somit werden die mit Kommentar 0 gekennzeichneten Bedingungen niemals erfüllt, was möglicherweise nicht genau der Logik der Arbeit entspricht, die der Programmierer erwartet hat.

Warnung N5

Analyzer Warnung: V3123[CWE-783] Vielleicht arbeitet der Operator '?:' Anders als erwartet. Seine Priorität ist niedriger als die Priorität anderer Betreiber in seinem Zustand. 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);
  }
}

Die Diagnose arbeitete an einer Linie:

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

Da die Variable j mehrere Zeilen oben auf Null initialisiert ist , gibt der ternäre Operator false zurück . Aufgrund dieser Bedingung wird der Schleifenkörper nur einmal ausgeführt. Es scheint mir, dass dieser Code überhaupt nicht so funktioniert, wie es der Programmierer beabsichtigt hat.

Warnung N6

Analyzer Warnung: V3022 [CWE-571] Der Ausdruck 'installedPackageVersions.Count! = 1' ist immer wahr. 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);
    }
    ....
  }
  ....
}

Hier ist eine seltsame verschachtelte Bedingung: installiertePackageVersions.Count! = 1 , die immer wahr sein wird . Oft weist eine solche Warnung auf einen logischen Fehler im Code und in anderen Fällen lediglich auf eine redundante Prüfung hin.

Warnung N7

Analyzer Warnung: V3001 Links und rechts vom '||' befinden sich identische Unterausdrücke 'commandArguments.contains ("- apikey")'. Operator. 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");
}

Der Programmierer, der diesen Code geschrieben hat, hat die letzten beiden Zeilen kopiert und vergessen, sie zu bearbeiten. Aus diesem Grund haben Chocolatey-Benutzer die Möglichkeit verloren, den apikey- Parameter auf einige weitere Arten anzuwenden . Ähnlich wie bei den obigen Parametern kann ich folgende Optionen anbieten:

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

Fehler beim Kopieren und Einfügen können früher oder später in jedem Projekt mit viel Quellcode auftreten. Eine der besten Möglichkeiten, mit ihnen umzugehen, ist die statische Analyse.

PS Und wie immer tritt dieser Fehler am Ende einer mehrzeiligen Bedingung auf :). Siehe die Veröffentlichung „ Die Wirkung der letzten Zeile “.

Warnung N8

Analyzer Warnung: V3095 [CWE-476] Das Objekt 'installiertes Paket ' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 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)
  {
    ....
  }
  ....
}

Klassischer Fehler: Zuerst wird das installierte Paketobjekt verwendet und dann auf null geprüft . Diese Diagnose zeigt uns eines von zwei Problemen im Programm: Entweder ist installiertes Paket niemals null , was zweifelhaft ist, und dann ist die Überprüfung redundant, oder wir können möglicherweise einen schwerwiegenden Fehler im Code erhalten - einen Versuch, über eine Null-Verbindung darauf zuzugreifen.

Fazit


Also haben wir einen weiteren kleinen Schritt getan - jetzt ist die Verwendung von PVS-Studio noch einfacher und bequemer geworden. Ich möchte auch sagen, dass Chocolatey ein guter Paketmanager mit einer kleinen Anzahl von Fehlern im Code ist, die bei Verwendung von PVS-Studio noch geringer werden können.

Wir laden Sie ein, PVS-Studio herunterzuladen und auszuprobieren. Die regelmäßige Verwendung eines statischen Analysators verbessert die Qualität und Zuverlässigkeit des von Ihrem Team entwickelten Codes und hilft, viele Zero-Day-Schwachstellen zu vermeiden .

PS


Vor der Veröffentlichung haben wir den Artikel an die Chocolatey-Entwickler gesendet und sie haben ihn gut angenommen. Wir fanden nichts Kritisches, aber sie mochten zum Beispiel den Fehler, den wir im Zusammenhang mit dem API-Schlüssel gefunden haben.



Wenn Sie diesen Artikel einem englischsprachigen Publikum zugänglich machen möchten, verwenden Sie bitte den Link zur Übersetzung: Vladislav Stolyarov. PVS-Studio ist jetzt in Chocolatey: Chocolatey unter Azure DevOps prüfen .

All Articles