PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.
Wir arbeiten weiterhin daran, die Nutzung von PVS-Studio zu vereinfachen. Jetzt ist unser Analyzer ĂŒber Chocolatey, den 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 gehen, prĂŒfen wir den Quellcode von Chocolatey. Azure DevOps wird als CI-System fungieren.

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

Ich empfehle, auf den ersten Artikel zur Integration mit Azure DevOps zu achten, da in diesem Fall einige Punkte ausgelassen wurden, um Wiederholungen zu vermeiden.

Also, die Helden dieses Artikels:

PVS-Studio — ein Werkzeug zur statischen Codeanalyse, das entwickelt wurde, um Fehler und potenzielle Schwachstellen in Programmen, die in C, C++, C# und Java geschrieben sind, zu entdecken. 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 statische Codeanalyse zur ÜberprĂŒfung Ihrer Projekte ausprobieren möchten, empfehlen wir Ihnen, sich mit Artikel darĂŒber, wie Sie die interessantesten Warnungen von PVS-Studio schnell ansehen und die Möglichkeiten dieses Tools bewerten können.

Azure DevOps — eine Sammlung von cloudbasierten Dienstleistungen, die gemeinsam den gesamten Entwicklungsprozess abdecken. Diese Plattform umfasst Werkzeuge wie Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos und Azure Test Plans, die den Softwareentwicklungsprozess beschleunigen und die QualitĂ€t erhöhen.

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

Zur Verwendung von Chocolatey

Sie können sehen, wie Sie den Paketmanager selbst installieren, indem Sie auf diese dem Link. Die vollstĂ€ndige Dokumentation zur Installation des Analyzers ist verfĂŒgbar unter dem Link im Abschnitt „Installation mit dem Paketmanager Chocolatey“. Kurz gebe ich einige Punkte von dort wieder.

Befehl zur Installation der neuesten Version des Analyzers:

choco install pvs-studio

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

choco install pvs-studio --version=7.05.35617.2075

StandardmĂ€ĂŸig wird nur der Core-Analyzer installiert - die Komponente Core. Alle anderen Flags (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) können ĂŒber —package-parameters ĂŒbergeben werden.

Beispielbefehl, der den Analyzer mit dem Plugin fĂŒr Visual Studio 2019 installiert:

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

Schauen wir uns nun ein Beispiel fĂŒr die benutzerfreundliche Verwendung des Analyzers unter Azure DevOps an.

Einstellungen

Ich erinnere daran, dass es zu Themen wie der Registrierung eines Kontos, der Erstellung von Build-Pipelines und der Synchronisation des Kontos mit einem Projekt im Repository auf GitHub separate Artikel. Unsere Einrichtung beginnt jedoch sofort mit dem Schreiben der Konfigurationsdatei.

ZunĂ€chst konfigurieren wir den Auslöser, indem wir angeben, dass wir nur bei Änderungen in master dem Branch starten:

trigger:
- master

Als nĂ€chstes mĂŒssen wir die virtuelle Maschine auswĂ€hlen. Momentan wird es ein Microsoft-hosted Agent mit Windows Server 2019 und Visual Studio 2019 sein:

pool:
  vmImage: 'windows-latest'

Kommen wir zum Hauptteil der Konfigurationsdatei (Block steps). Obwohl auf der virtuellen Maschine keine beliebige Software installiert werden kann, habe ich keinen Docker-Container hinzugefĂŒgt. Wir können Chocolatey als Erweiterung fĂŒr Azure DevOps hinzufĂŒgen. DafĂŒr gehen wir zu dem Link. Klicken Sie auf Get it free. Falls Sie bereits angemeldet sind, wĂ€hlen Sie einfach Ihr Konto aus; andernfalls folgen Sie dem gleichen Verfahren nach der Anmeldung.

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Hier mĂŒssen wir auswĂ€hlen, wo wir die Erweiterung hinzufĂŒgen werden, und auf die SchaltflĂ€che klicken Installieren.

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Nachdem die Installation erfolgreich abgeschlossen ist, klicken wir auf Proceed to organization:

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Nun können wir die Vorlage fĂŒr die Chocolatey-Aufgabe im Fenster sehen tasks beim Bearbeiten der Konfigurationsdatei azure-pipelines.yml:

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

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

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Hier mĂŒssen wir auswĂ€hlen install im Befehlsfeld. In Nuspec File Name geben wir den Namen des benötigten Pakets an – pvs-studio. Wenn keine Version angegeben ist, wird die neueste installiert, was uns vollkommen zufriedenstellt. Klicken Sie auf die SchaltflĂ€che add und sehen Sie die erstellte Aufgabe in der Konfigurationsdatei.

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

Kommen wir nun zum Hauptteil unserer Datei:

- task: CmdLine@2
  inputs:
    script: 

Jetzt mĂŒssen wir eine Lizenzdatei fĂŒr den Analyzer erstellen. Hier PVSNAME und PVSKEY – sind die Namen der Variablen, deren Werte wir in den Einstellungen angeben. Sie speichern den Login und den LizenzschlĂŒssel von PVS-Studio. Um ihre Werte zu setzen, öffnen wir das MenĂŒ Variables->New variable. Lassen Sie uns die Variablen PVSNAME fĂŒr den Login und PVSKEY fĂŒr den Analyse-SchlĂŒssel. Vergessen Sie nicht, das KĂ€stchen anzukreuzen Halten Sie diesen Wert geheim fĂŒr PVSKEY. Befehlscode:

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

Lassen Sie uns das Projekt mit der in dem Repository vorhandenen bat-Datei zusammenstellen:

call build.bat

Lassen Sie uns einen Ordner erstellen, in dem die Ergebnisse der Analyse gespeichert werden:

call mkdir PVSTestResults

Lassen Sie uns die Analyse des Projekts starten:

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

Konvertieren wir unseren Bericht mit dem PlogConverter in das HTML-Format:

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

Jetzt mĂŒssen wir einen Job 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 fĂŒr die AusfĂŒhrung des Jobs. Wir werden den Bericht abrufen, indem wir zum Tab Job gehen.

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Das Chocolatey-Projekt besteht aus insgesamt 37615 Zeilen C#-Code. Betrachten wir einige der gefundenen Fehler.

Ergebnisse der ÜberprĂŒfung

Warnung N1

Warnung des Analysewerkzeugs: V3005 Die ‘Provider’-Variable 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 Analysewerkzeug hat die Zuweisung einer Variablen zu sich selbst entdeckt, was keinen Sinn ergibt. Wahrscheinlich sollte an der Stelle einer dieser Variablen eine andere stehen. Oder es handelt sich um einen Tippfehler, und die zusÀtzliche Zuweisung kann einfach gelöscht werden.

Warnung N2

Warnung des Analysewerkzeugs: V3093 [CWE-480] Der ‘&’-Operator bewertet beide Operanden. Vielleicht sollte stattdessen ein Kurzschluss-‘&&’-Operator 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 && liegt darin, dass die linke Seite des Ausdrucks — false, es wird trotzdem der rechte Teil berechnet, was in diesem Fall ĂŒberflĂŒssige MethodenausfĂŒhrungen impliziert system.directory_exists.

Im betrachteten Fragment handelt es sich um einen kleinen Mangel. Ja, dieser Ausdruck kann optimiert werden, indem der Operator & durch den Operator && ersetzt wird, aber aus praktischer Sicht hat das keinen Einfluss. In anderen FÀllen kann jedoch die Verwirrung zwischen & und && ernsthafte Probleme verursachen, wenn der rechte Teil des Ausdrucks mit inkorrekten oder unzulÀssigen Werten arbeitet. Zum Beispiel gibt es in unserer Sammlung von Fehlern, die mit der Diagnose V3093 aufgedeckt wurden, folgenden Fall:

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

Selbst wenn der Index k inkorrekt ist, wird er verwendet, um auf das Array-Element zuzugreifen. In der Folge wird eine Ausnahme ausgelöst 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 in der Funktionsweise des ternĂ€ren Operators. Lassen Sie uns das nĂ€her betrachten: Wenn die Bedingung, die ich mit der Zahl 1 gekennzeichnet habe, erfĂŒllt ist, gehen wir zur Bedingung 2 ĂŒber, die immer true, also wird Zeile 3 ausgefĂŒhrt. Wenn jedoch Bedingung 1 falsch ist, gehen wir zu der Zeile, die mit der Zahl 4 gekennzeichnet ist, wobei die Bedingung ebenfalls immer true, also wird Zeile 5 ausgefĂŒhrt. Somit werden die Bedingungen, die mit dem Kommentar 0 gekennzeichnet sind, niemals ausgefĂŒhrt, 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 anderen 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 hat fĂŒr die Zeile ausgelöst:

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

Da die Variable j Ein paar Zeilen höher wird es mit null initialisiert, der ternĂ€re Operator gibt den Wert zurĂŒck. false. Aufgrund dieser Bedingung wird der Schleifenrumpf nur einmal ausgefĂŒhrt. Ich habe das GefĂŒhl, dass dieser Codeabschnitt ganz anders funktioniert, 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 geschachtelte Bedingung: installedPackageVersions.Count != 1, die immer wahr sein wird true. Solche Warnungen deuten oft auf einen logischen Fehler im Code hin, in anderen FĂ€llen einfach auf ĂŒberflĂŒssige ÜberprĂŒfungen.

Warnung N7

Warnung des Analysewerkzeugs: V3001 Es gibt identische Teil-AusdrĂŒ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 geschrieben hat, hat die letzten beiden Zeilen kopiert und vergessen, sie zu bearbeiten. Dadurch haben die Benutzer von Chocolatey die Möglichkeit verloren, den Parameter apikey auf noch einige andere Arten zu verwenden. Analog zu den oben genannten Parametern schlage ich folgende Varianten vor:

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

Copy-Paste-Fehler treten frĂŒher oder spĂ€ter in jedem Projekt mit viel Code auf, und eines der besten Mittel zur BekĂ€mpfung ist die statische Analyse.

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

Warnung N8

Warnung des Analysewerkzeugs: V3095 [CWE-476] Das ‘installedPackage’-Objekt wurde verwendet, bevor es auf null ĂŒberprĂŒft wurde. ÜberprĂŒfen Sie die Zeilen: 910, 917. NugetService.cs 910

öffentliche virtuelle ConcurrentDictionary<string, PackageResult> get_outdated(....)
{
  ....
  var pinnedPackageResult = outdatedPackages.GetOrAdd(
    packageName, 
    new PackageResult(installedPackage, 
                      _fileSystem.combine_paths(
                        ApplicationParameters.PackagesLocation, 
                        installedPackage.Id)));
  ....
  wenn (   installedPackage != null
      && !string.IsNullOrWhiteSpace(installedPackage.Version.SpecialVersion) 
      && !config.UpgradeCommand.ExcludePrerelease)
  {
    ....
  }
  ....
}

Klassischer Fehler: Zuerst wird das Objekt installedPackage verwendet, dann wird es auf null. Diese Diagnose weist auf eines von zwei Problemen im Programm hin: entweder installedPackage niemals gleich null, was zweifelhaft ist, und die PrĂŒfung dann ĂŒberflĂŒssig ist, oder wir könnten potenziell einen schweren Fehler im Code bekommen – den Versuch, auf eine Nullreferenz zuzugreifen.

Fazit

Hier haben wir einen weiteren kleinen Schritt gemacht – jetzt ist die Nutzung von PVS-Studio noch einfacher und bequemer geworden. Ich möchte auch sagen, dass Chocolatey ein guter Paketmanager ist, mit wenigen Fehlern im Code, die noch geringer wĂ€ren, wenn PVS-Studio verwendet wĂŒrde.

Wir laden ein herunterladen und PVS-Studio auszuprobieren. Die regelmĂ€ĂŸige Verwendung des statischen Analysators wird die QualitĂ€t und ZuverlĂ€ssigkeit des von Ihrem Team entwickelten Codes erhöhen und helfen, viele Zero-Day-Schwachstellen.

P.S.

Vor der Veröffentlichung haben wir den Artikel an die Entwickler von Chocolatey gesendet, und sie haben ihn gut angenommen. Kritisches wurde von uns nicht gefunden, aber ihnen hat zum Beispiel der Fehler gefallen, den wir in Bezug auf den SchlĂŒssel „api-key“ gefunden haben.

PVS-Studio jetzt in Chocolatey: ÜberprĂŒfung von Chocolatey unter Azure DevOps.

Wenn 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 Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server đŸ”„ ZuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster