PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps
Wir arbeiten weiterhin daran, die Nutzung von PVS-Studio zu erleichtern. Unser Analysetool ist jetzt in Chocolatey, dem Paketmanager für Windows, verfügbar. Wir glauben, dass dies die Bereitstellung von PVS-Studio, insbesondere in Cloud-Diensten, erleichtert. Um konkret zu werden, überprüfen wir den Quellcode von Chocolatey. Azure DevOps wird als CI-System fungieren.

Hier ist eine Liste unserer weiteren Artikel zum Thema Integration mit Cloud-Systemen:

Ich empfehle, auf den ersten Artikel über die Integration mit Azure DevOps zu achten, da in diesem Fall einige Punkte weggelassen wurden, um Doppelungen zu vermeiden.

Also, die Hauptakteure dieses Artikels:

PVS-Studio — ein Tool zur statischen Codeanalyse, das entwickelt wurde, um Fehler und potenzielle Schwachstellen in Programmen zu identifizieren, die in C, C++, C# und Java geschrieben sind. 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 bestimmt ist. Wenn Sie zum ersten Mal die statische Codeanalyse ausprobieren, um Ihre Projekte zu überprüfen, empfehlen wir Ihnen, sich mit Artikel auseinanderzusetzen, wie Sie schnell die interessantesten Warnungen von PVS-Studio einsehen und die Möglichkeiten dieses Tools bewerten können.

Azure DevOps. — eine Sammlung von Cloud-Diensten, die den gesamten Entwicklungsprozess abdecken. Die Plattform umfasst Tools wie Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos und Azure Test Plans, die den Softwareentwicklungsprozess beschleunigen und die Qualität verbessern.

Chocolatey – ein Open-Source-Paketmanager für Windows. Ziel des Projekts ist es, den gesamten Lebenszyklus von Software von der Installation über Updates bis hin zur Deinstallation in Windows-Betriebssystemen zu automatisieren.

Über die Verwendung von Chocolatey

Klicken Sie hier, um zu sehen, wie Sie den Paketmanager selbst installieren können. über diesen Link verfügbar. Die vollständige Dokumentation zur Installation des Analysewerkzeugs ist verfügbar unter über diesen Link verfügbar im Abschnitt „Installation mit dem Paketmanager Chocolatey“. Hier sind einige wichtige Punkte zusammengefasst.

Der Befehl zur Installation der neuesten Version des Analysewerkzeugs lautet:

choco install pvs-studio

Der Befehl zur Installation einer bestimmten Version des PVS-Studio-Pakets lautet:

choco install pvs-studio --version=7.05.35617.2075

Standardmäßig wird nur der Kern des Analysewerkzeugs installiert – die Komponente Core. Alle anderen Flags (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) können mit —package-parameters übergeben werden.

Ein Beispielbefehl, der das Analysewerkzeug mit dem Plugin für Visual Studio 2019 installiert:

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

Nun betrachten wir ein praktisches Beispiel für die Verwendung des Analysewerkzeugs mit Azure DevOps.

Konfiguration

Ich erinnere daran, dass es zu Themen wie der Registrierung eines Kontos, der Erstellung einer Build-Pipeline und der Synchronisierung des Kontos mit einem in einem GitHub-Repository gespeicherten Projekt eine separate Artikel. Unsere Konfiguration beginnt direkt mit dem Schreiben der Konfigurationsdatei.

Zunächst konfigurieren wir den Trigger für die Ausführung, indem wir angeben, dass die Ausführung nur für Änderungen in master dem Branch erfolgt:

trigger:
- master

Als Nächstes wählen wir die virtuelle Maschine aus. Dies wird aktuell ein von Microsoft gehosteter Agent mit Windows Server 2019 und Visual Studio 2019 sein:

pool:
  vmImage: 'windows-latest'

Lassen Sie uns zum Hauptteil der Konfigurationsdatei (Block steps). Obwohl wir auf der virtuellen Maschine keine beliebige Software installieren können, habe ich keinen Docker-Container hinzugefügt. Wir können Chocolatey als Erweiterung für Azure DevOps hinzufügen. Gehen wir dazu zu über diesen Link verfügbar. Klicken Sie auf Jetzt kostenlos erhalten. Wenn Sie bereits angemeldet sind, wählen Sie einfach Ihr Konto aus; wenn nicht, melden Sie sich an und wiederholen Sie den Vorgang.

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Hier müssen wir auswählen, wo wir die Erweiterung hinzufügen, und die Schaltfläche Installieren.

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Nach erfolgreicher Installation klicken wir auf Zur Organisation fortfahren:

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Jetzt können wir die Vorlage für die Chocolatey-Aufgabe im Fenster tasks beim Bearbeiten der Konfigurationsdatei azure-pipelines.yml:

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Klicken Sie auf Chocolatey und wir sehen die Liste der Felder:

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Hier müssen wir auswählen install im Feld mit den Befehlen. In Nuspec File Name geben wir den Namen des gewünschten Pakets ein – pvs-studio. Wenn wir die Version nicht angeben, wird die neueste installiert, was für uns völlig in Ordnung ist. Klicken wir auf die Schaltfläche add und sehen wir die generierte Aufgabe in der Konfigurationsdatei.

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

Lass uns nun zum Hauptteil unserer Datei übergehen:

- task: CmdLine@2
  inputs:
    script: 

Jetzt müssen wir eine Lizenzdatei für den Analyzer erstellen. Hier PVSNAME und PVSKEY – das sind die Namen der Variablen, deren Werte wir in den Einstellungen angeben. Sie werden den Login und den Lizenzschlüssel von PVS-Studio speichern. Um ihre Werte festzulegen, öffnen wir das Menü Variablen->Neue Variable. Wir erstellen Variablen PVSNAME für den Login und PVSKEY für den Schlüssel des Analyzers. Vergessen Sie nicht, das Häkchen Wert geheim halten für PVSKEY. Der Befehlscode lautet:

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

Wir bauen das Projekt mithilfe der bat-Datei zusammen, die im Repository liegt:

call build.bat

Wir erstellen einen Ordner, in dem die Dateien mit den Ergebnissen der Analyse gespeichert werden:

call mkdir PVSTestResults

Wir starten die Analyse des Projekts:

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

Wir konvertieren unseren Bericht in das html-Format mithilfe des PlogConverter-Tools:

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

Jetzt müssen wir eine Aufgabe erstellen, um den Bericht exportieren zu können.

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

Die vollständige Konfigurationsdatei sieht so 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-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()

Klicken wir Speichern->Speichern->Ausführen Um die Aufgabe auszuführen. Wir werden den Bericht herunterladen, indem wir zum Aufgabentab wechseln.

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Das Chocolatey-Projekt enthält insgesamt 37.615 Zeilen C#-Code. Schauen wir uns einige der gefundenen Fehler an.

Überprüfungsergebnisse

Warnung Nr. 1

Warnung des Analysewerkzeugs: 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 Analyzer hat eine Zuweisung der Variablen zu sich selbst festgestellt, was keinen Sinn ergibt. Wahrscheinlich sollte anstelle einer dieser Variablen eine andere stehen. Oder es handelt sich um einen Tippfehler, und die überflüssige Zuweisung kann einfach entfernt werden.

Warnung N2

Warnung des Analysewerkzeugs: V3093 [CWE-480] Der ‚&‘ Operator evaluiert beide Operanden. Vielleicht 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 der linke Teil des Ausdrucks false, trotzdem der rechte Teil ausgewertet wird, was in diesem Fall überflüssige Methodenaufrufe impliziert system.directory_exists.

In dem betrachteten Fragment handelt es sich um ein kleines Versehen. Ja, diese Bedingung kann optimiert werden, indem der Operator & durch den Operator && ersetzt wird, aber aus praktischer Sicht hat das keine Auswirkung. In anderen Fällen kann jedoch die Verwirrung zwischen & und && ernsthafte Probleme verursachen, wenn der rechte Teil des Ausdrucks mit ungültigen/inkorrekten Werten arbeitet. Zum Beispiel haben wir in unserer Fehlerkollektion, die durch die Diagnose V3093 identifiziert wurde,, einen solchen Fall:

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

Selbst wenn der Index k ist ungültig und wird zum Zugriff auf das Array-Element verwendet. Daher wird eine Ausnahme generiert. IndexOutOfRangeException.

Warnungen N3, N4

Warnung des Analysewerkzeugs: V3022 [CWE-571] Ausdruck ‘shortPrompt’ ist immer wahr. InteractivePrompt.cs 101
Warnung des Analysewerkzeugs: V3022 [CWE-571] 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 der Funktionsweise des ternären Operators. Lassen Sie uns näher betrachten: Wenn die Bedingung, die ich mit der Nummer 1 markiert habe, erfüllt ist, gehen wir zur Bedingung 2 über, die immer true, was bedeutet, dass Zeile 3 ausgeführt wird. Wenn jedoch Bedingung 1 falsch ist, gehen wir zur Zeile mit der Nummer 4, deren Bedingung ebenfalls immer true, was bedeutet, dass Zeile 5 ausgeführt wird. Somit werden die Bedingungen, die mit Kommentar 0 markiert sind, niemals erfüllt, was möglicherweise nicht die Logik ist, die der Programmierer erwartet hat.

Warnung N5

Warnung des Analysewerkzeugs: V3123 [CWE-783] Vielleicht funktioniert der ‘?:’ Operator anders als erwartet. Seine Priorität ist niedriger als die anderer Operatoren in seiner Bedingung. 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 = 0 && j != 0 ? description [j++ - 1] == '{' : false);
    ....
    return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
  }
}

Die Diagnose wurde für die Zeile ausgelöst:

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

Da die Variable j ein paar Zeilen weiter oben mit null initialisiert wird, gibt der ternäre Operator den Wert zurück false. Aufgrund dieser Bedingung wird der Schleifeninhalt nur einmal ausgeführt. Ich denke, dieser Codeabschnitt funktioniert ganz anders, als der Programmierer beabsichtigt hat.

Warnung N6

Warnung des Analysewerkzeugs: V3022 [CWE-571] 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 = "Alle Versionen";
    if (installedPackageVersions.Count != 1)
    {
      choices.Add(allVersionsChoice);
    }
    ....
  }
  ....
}

Hier ist eine seltsame verschachtelte Bedingung: installedPackageVersions.Count != 1, die immer wahr sein wird true. Diese Warnung deutet oft auf einen logischen Fehler im Code hin, in anderen Fällen auf übermäßige Prüfungen.

Warnung N7

Warnung des Analysewerkzeugs: V3001 Es gibt identische Unterausdrücke 'commandArguments.contains("-apikey")' links und rechts des '||' Operators. 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 Codeabschnitt verfasst hat, hat die letzten beiden Zeilen kopiert und vergessen, sie zu bearbeiten. Dadurch haben Nutzer von Chocolatey die Möglichkeit verloren, den Parameter apikey auf andere Weise zu verwenden. Ähnlich wie bei den oben genannten Parametern schlage ich die folgenden Varianten vor:

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

Copy-Paste-Fehler treten in Projekten mit umfangreichem Quellcode früher oder später häufig auf. Eines der besten Mittel zu ihrer Bekämpfung ist die statische Analyse.

P.S. Und wie immer neigt dieser Fehler dazu, am Ende einer mehrzeiligen Bedingung aufzutreten :). Siehe Beitrag "Effekt der letzten Zeile".

Warnung N8

Warnung des Analysewerkzeugs: V3095 [CWE-476] Das Objekt 'installedPackage' wurde verwendet, bevor es auf null überprüft wurde. Überprüfen Sie die Zeilen: 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)
  {
    ....
  }
  ....
}

Klassischer Fehler: Zuerst wird das Objekt installedPackage verwendet und dann auf nullüberprüft. Diese Diagnose weist auf eines von zwei Problemen im Programm hin: Entweder installedPackage niemals gleich null, was fraglich ist, und dann wäre die Überprüfung überflüssig, oder wir könnten potenziell einen ernsthaften Fehler im Code erhalten – einen Versuch, auf einen Nullverweis zuzugreifen.

Fazit

Wir haben einen weiteren kleinen Schritt gemacht – die Nutzung von PVS-Studio ist jetzt noch einfacher und bequemer. Ich möchte auch sagen, dass Chocolatey ein guter Paketmanager ist, der nur wenige Fehler im Code aufweist, von denen es noch weniger geben könnte, wenn PVS-Studio verwendet wird.

Wir laden ein heruntergeladen und PVS-Studio auszuprobieren. Die regelmäßige Nutzung des statischen Analysators wird die Qualität und Zuverlässigkeit des von Ihrem Team entwickelten Codes verbessern und viele Zero-Day-Schwachstellen.

P.S.

Vor der Veröffentlichung haben wir den Artikel den Entwicklern von Chocolatey zugesandt, und sie haben ihn gut aufgenommen. Wir haben nichts Kritisches gefunden, aber sie waren zum Beispiel von dem Fehler beeindruckt, den wir mit dem Schlüssel „api-key“ gefunden haben.

PVS-Studio jetzt in Chocolatey: Überprüfung von Chocolatey über Azure DevOps

Falls Sie diesen Artikel mit einem englischsprachigen Publikum teilen möchten, verwenden Sie bitte den Link zur Übersetzung: Vladislav Stolyarov. PVS-Studio ist jetzt in Chocolatey: Überprüfung von Chocolatey unter Azure DevOps.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster