
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
