
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:
— 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 darüber, wie Sie die interessantesten Warnungen von PVS-Studio schnell ansehen und die Möglichkeiten dieses Tools bewerten können.
— 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.
– 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 . Die vollständige Dokumentation zur Installation des Analyzers ist verfügbar unter 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-studioBefehl zur Installation einer bestimmten Version des PVS-Studio-Pakets:
choco install pvs-studio --version=7.05.35617.2075Standardmäß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 . 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:
- masterAls 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 . 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.

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

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

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

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

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.batLassen Sie uns einen Ordner erstellen, in dem die Ergebnisse der Analyse gespeichert werden:
call mkdir PVSTestResultsLassen 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.plogJetzt 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.
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: 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: [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, , 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: [CWE-571] Ausdruck 'shortPrompt' ist immer wahr. InteractivePrompt.cs 101
Warnung des Analysewerkzeugs: [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: [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: [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: 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 "".
Warnung N8
Warnung des Analysewerkzeugs: [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 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 .
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.
Wenn Sie diesen Artikel mit einem englischsprachigen Publikum teilen möchten, verwenden Sie bitte den Link zur Übersetzung: Vladislav Stolyarov. .
Quelle: habr.com
