Nous continuons Ă rendre l'utilisation de PVS-Studio plus pratique. Notre analyseur est dĂ©sormais disponible dans Chocolatey, le gestionnaire de packages pour Windows. Nous pensons que cela facilitera le dĂ©ploiement de PVS-Studio, en particulier dans les services cloud. Afin de ne pas aller loin, vĂ©rifiez le code source du mĂȘme Chocolatey. Le systĂšme CI sera Azure DevOps.Voici une liste de nos autres articles sur l'intĂ©gration cloud:Je vous conseille de faire attention au premier article sur l'intĂ©gration avec Azure DevOps, car dans ce cas certains points sont omis afin de ne pas ĂȘtre dupliquĂ©s.Ainsi, les hĂ©ros de cet article:PVS-Studio est un outil d'analyse de code statique conçu pour dĂ©tecter les erreurs et les vulnĂ©rabilitĂ©s potentielles dans les programmes Ă©crits en C, C ++, C # et Java. Il fonctionne sur les systĂšmes 64 bits sous Windows, Linux et macOS et peut analyser le code conçu pour les plates-formes ARM 32 bits, 64 bits et intĂ©grĂ©es. Si c'est la premiĂšre fois que vous essayez l'analyse de code statique pour vĂ©rifier vos projets, nous vous recommandons de lire l' article sur la façon de voir rapidement les avertissements les plus intĂ©ressants de PVS-Studio et d'Ă©valuer les capacitĂ©s de cet outil.Azure DevOps- Un ensemble de services cloud couvrant conjointement l'ensemble du processus de dĂ©veloppement. La plateforme comprend des outils tels que Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, qui accĂ©lĂšrent le processus de crĂ©ation de logiciels et amĂ©liorent sa qualitĂ©.Chocolatey est un gestionnaire de packages open source pour Windows. L'objectif du projet est d'automatiser l'ensemble du cycle de vie du logiciel, de l'installation Ă la mise Ă jour et Ă la dĂ©sinstallation sur les systĂšmes d'exploitation Windows.Ă propos de Chocolatey
Vous pouvez voir comment installer le gestionnaire de packages via ce lien . Une documentation complÚte sur l'installation de l'analyseur est disponible sur le lien dans la section «Installation à l'aide du gestionnaire de paquets Chocolatey». Je vais répéter briÚvement quelques points à partir de là .Commande pour installer la derniÚre version de l'analyseur:choco install pvs-studio
La commande pour installer une version spécifique du package PVS-Studio:choco install pvs-studio --version=7.05.35617.2075
Par dĂ©faut, seul le noyau de l'analyseur est installĂ© - le composant Core. Tous les autres indicateurs (autonome, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) peuvent ĂȘtre transmis Ă l'aide de --package-parameters.Un exemple de commande qui installera l'analyseur avec un plug-in pour Visual Studio 2019:choco install pvs-studio --package-parameters="'/MSVS2019'"
Voyons maintenant un exemple d'utilisation pratique de l'analyseur sous Azure DevOps.Personnalisation
Je vous rappelle qu'il existe un article distinct sur des questions telles que l'enregistrement d'un compte, la création d'un pipeline de génération et la synchronisation d'un compte avec un projet dans le référentiel sur GitHub . Notre installation commencera immédiatement en écrivant un fichier de configuration.Tout d' abord, configurez le déclencheur pour déclencher, ce qui indique que nous ne courons des changements dans le maßtre branche:trigger:
- master
Ensuite, nous devons choisir une machine virtuelle. Pour le moment, ce sera un agent hébergé par Microsoft avec Windows Server 2019 et Visual Studio 2019:pool:
vmImage: 'windows-latest'
Passons au corps du fichier de configuration (bloc Ă©tapes ). MalgrĂ© le fait qu'un logiciel arbitraire ne peut pas ĂȘtre installĂ© sur une machine virtuelle, je n'ai pas ajoutĂ© de conteneur Docker. Nous pouvons ajouter Chocolatey comme extension pour Azure DevOps. Pour ce faire, cliquez sur le lien . Cliquez sur Obtenez-le gratuitement . De plus, si vous ĂȘtes dĂ©jĂ autorisĂ©, sĂ©lectionnez simplement votre compte, et sinon, faites de mĂȘme aprĂšs l'autorisation.Ici, vous devez choisir oĂč nous ajouterons l'extension, puis cliquez sur le bouton Installer .AprĂšs une installation rĂ©ussie, cliquez sur ProcĂ©der Ă l'organisation :Vous pouvez maintenant voir le modĂšle de la tĂąche Chocolatey dans la fenĂȘtre des tĂąches lors de la modification du fichier de configuration azure-pipelines.yml:Cliquez sur Chocolatey et voyez une liste de champs:Ici, nous devons sĂ©lectionner installer dans le champ de commande. Dans Nuspec File Name, spĂ©cifiez le nom du package souhaitĂ© - pvs-studio. Si vous ne spĂ©cifiez pas de version, cette derniĂšre sera installĂ©e, ce qui nous convient parfaitement. Cliquez sur le bouton Ajouter et voyez la tĂąche formĂ©e dans le fichier de configuration.steps:
- task: ChocolateyCommand@0
inputs:
command: 'install'
installPackageId: 'pvs-studio'
Passons maintenant Ă la partie principale de notre fichier:- task: CmdLine@2
inputs:
script:
Nous devons maintenant créer un fichier avec la licence de l'analyseur. Ici PVSNAME et PVSKEY sont les noms des variables dont nous spécifions les valeurs dans les paramÚtres. Ils stockent la clé de connexion et de licence PVS-Studio. Pour définir leurs valeurs, ouvrez le menu Variables-> Nouvelle variable . Créez les variables PVSNAME pour la connexion et PVSKEY pour la clé de l'analyseur. N'oubliez pas de cocher la case Garder cette valeur secrÚte pour PVSKEY . Code d'équipe:all "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials
âu $(PVSNAME) ân $(PVSKEY)
Construisons le projet en utilisant le fichier bat se trouvant dans le référentiel:all build.bat
Créez un dossier dans lequel se trouveront les fichiers contenant les résultats du travail de l'analyseur:all mkdir PVSTestResults
Exécutez l'analyse du projet:all "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe"
ât .\src\chocolatey.sln âo .\PVSTestResults\Choco.plog
Nous convertissons notre rapport au format html Ă l'aide de l'utilitaire Plogonverter:all "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe"
ât html âo \PVSTestResults\ .\PVSTestResults\Choco.plog
Vous devez maintenant créer une tùche afin de pouvoir télécharger le rapport.- task: PublishBuildArtifacts@1
inputs:
pathToPublish: PVSTestResults
artifactName: PVSTestResults
condition: always()
Le fichier de configuration complet ressemble Ă ceci: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()
Cliquez sur Enregistrer-> Enregistrer-> Exécuter pour démarrer la tùche. Déchargez le rapport en accédant à l'onglet des tùches.
Le projet Chocolatey contient un total de 37 615 lignes de code C #. Considérez certaines des erreurs trouvées.Résultats de validation
Avertissement N1Analyzer Avertissement: V3005 La variable 'Provider' est assignĂ©e Ă elle-mĂȘme. CrytpoHashProviderSpecs.cs 38public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}
L'analyseur a trouvĂ© l'affectation d'une variable Ă lui-mĂȘme, ce qui n'a pas de sens. TrĂšs probablement, Ă la place de l'une de ces variables devrait en ĂȘtre une autre. Eh bien, ou c'est une faute de frappe, et une affectation inutile peut simplement ĂȘtre supprimĂ©e.Avertissement Avertissement de l'analyseur N2 : V3093 [CWE-480] L'opĂ©rateur '&' Ă©value les deux opĂ©randes. Peut-ĂȘtre qu'un opĂ©rateur de court-circuit '&&' devrait ĂȘtre utilisĂ© Ă la place. Platform.cs 64public 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;
}
}
La diffĂ©rence entre l' opĂ©rateur & et l'opĂ©rateur && est que si le cĂŽtĂ© gauche de l'expression est faux , le cĂŽtĂ© droit sera toujours calculĂ©, ce qui dans ce cas implique des appels supplĂ©mentaires Ă la mĂ©thode system.directory_exists .Dans ce fragment, il s'agit d'un dĂ©faut mineur. Oui, cette condition peut ĂȘtre optimisĂ©e en remplaçant l'opĂ©rateur & par l'opĂ©rateur &&, mais d'un point de vue pratique, cela n'affecte rien. Cependant, dans d'autres cas, la confusion entre & et && peut entraĂźner de graves problĂšmes lorsque le cĂŽtĂ© droit de l'expression fonctionne avec des valeurs incorrectes / non valides. Par exemple, dans notre collection d'erreurs dĂ©tectĂ©es par le diagnostic V3093 , il y a un tel cas:if ((k < nct) & (s[k] != 0.0))
MĂȘme si l'index k est incorrect, il sera utilisĂ© pour accĂ©der Ă l'Ă©lĂ©ment de tableau. Par consĂ©quent, une exception IndexOutOfRangeException sera levĂ©e .Avertissements N3, N4Analyseur Avertissement: V3022 [CWE-571] L'expression 'shortPrompt' est toujours vraie. InteractivePrompt.cs 101Avertissement de l'analyseur: V3022 [CWE-571] L'expression 'shortPrompt' est toujours vraie. InteractivePrompt.cs 105public static string
prompt_for_confirmation(.... bool shortPrompt = false, ....)
{
....
if (shortPrompt)
{
var choicePrompt = choice.is_equal_to(defaultChoice)
?
shortPrompt
?
"[[{0}]{1}]".format_with(choice.Substring(0, 1).ToUpperInvariant(),
choice.Substring(1,choice.Length - 1))
:
"[{0}]".format_with(choice.ToUpperInvariant())
:
shortPrompt
?
"[{0}]{1}".format_with(choice.Substring(0,1).ToUpperInvariant(),
choice.Substring(1,choice.Length - 1))
:
choice;
....
}
....
}
Dans ce cas, il y a une Ă©trange logique de l'opĂ©rateur ternaire. Examinons de plus prĂšs: si la condition marquĂ©e par le numĂ©ro 1 est remplie, nous passons Ă la condition 2, qui est toujours vraie , ce qui signifie que la ligne 3 est satisfaite. Si la condition 1 se rĂ©vĂšle ĂȘtre fausse, nous allons Ă la ligne marquĂ©e par le numĂ©ro 4, la condition dans laquelle est Ă©galement toujours vrai , ce qui signifie que la ligne 5 est exĂ©cutĂ©e. Ainsi, les conditions marquĂ©es avec le commentaire 0 ne seront jamais remplies, ce qui peut ne pas ĂȘtre exactement la logique de travail que le programmeur attendait.Avertissement Avertissement de l'analyseur N5 : V3123[CWE-783] L'opĂ©rateur '?:' Fonctionne peut-ĂȘtre d'une maniĂšre diffĂ©rente de celle attendue. Sa prioritĂ© est infĂ©rieure Ă la prioritĂ© des autres opĂ©rateurs dans son Ă©tat. Options.cs 1019private 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);
}
}
Les diagnostics ont fonctionné sur une ligne:while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)
Puisque la variable j est initialisée à zéro plusieurs lignes ci-dessus, l'opérateur ternaire retournera false . En raison de cette condition, le corps de la boucle ne s'exécutera qu'une seule fois. Il me semble que ce morceau de code ne fonctionne pas du tout comme le programmeur le voulait.Avertissement Avertissement de l'analyseur N6 : V3022 [CWE-571] L'expression 'installedPackageVersions.Count! = 1' est toujours vraie. NugetService.cs 1405private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "All versions";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}
Voici une condition imbriquée étrange: installedPackageVersions.Count! = 1 , ce qui sera toujours vrai . Souvent, un tel avertissement indique une erreur logique dans le code, et dans d'autres cas, simplement une vérification redondante.Avertissement N7Analyzer Avertissement: V3001 Il existe des sous-expressions identiques 'commandArguments.contains ("- apikey")' à gauche et à droite de '||' opérateur. ArgumentsUtility.cs 42public 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");
}
Le programmeur qui a écrit ce morceau de code a copié les deux derniÚres lignes et a oublié de les modifier. Pour cette raison, les utilisateurs de Chocolatey ont perdu la possibilité d'appliquer le paramÚtre d' apikey de plusieurs façons. Semblable aux paramÚtres ci-dessus, je peux offrir de telles options:commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");
Les erreurs de copier-coller ont tĂŽt ou tard de grandes chances d'apparaĂźtre dans tout projet contenant beaucoup de code source, et l'une des meilleures façons de les traiter est l'analyse statique.PS Et, comme toujours, cette erreur a tendance Ă apparaĂźtre Ă la fin d'une condition multiligne :). Voir la publication « L'effet de la derniĂšre ligne ».Avertissement Avertissement de l'analyseur N8 : V3095 [CWE-476] L'objet 'installedPackage' a Ă©tĂ© utilisĂ© avant d'ĂȘtre vĂ©rifiĂ© par rapport Ă null. VĂ©rifiez les lignes: 910, 917. NugetService.cs 910public 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)
{
....
}
....
}
Erreur classique: tout d'abord, l'objet installedPackage est utilisé, puis il est vérifié pour null . Ce diagnostic nous indique l'un des deux problÚmes du programme: soit installedPackage n'est jamais nul , ce qui est douteux, puis la vérification est redondante, ou nous pouvons potentiellement obtenir une grave erreur dans le code - une tentative d'accÚs via un lien nul.Conclusion
Nous avons donc fait un autre petit pas - maintenant, l'utilisation de PVS-Studio est devenue encore plus facile et plus pratique. Je veux également dire que Chocolatey est un bon gestionnaire de paquets avec un petit nombre d'erreurs dans le code, qui pourraient devenir encore moins lors de l'utilisation de PVS-Studio.Nous vous invitons à télécharger et à essayer PVS-Studio. L'utilisation réguliÚre d'un analyseur statique améliorera la qualité et la fiabilité du code développé par votre équipe et aidera à prévenir de nombreuses vulnérabilités zero-day .PS
Avant la publication, nous avons envoyé l'article aux développeurs de Chocolatey, et ils l'ont bien accepté. Nous n'avons rien trouvé de critique, mais, par exemple, ils ont aimé l'erreur que nous avons trouvée concernant la clé api.
Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction: Vladislav Stolyarov. PVS-Studio est maintenant dans Chocolatey: vérification de Chocolatey sous Azure DevOps .