
Nous continuons à faciliter l'utilisation de PVS-Studio. Désormais, notre analyseur est disponible dans Chocolatey, le gestionnaire de paquets pour Windows. Nous pensons que cela simplifiera le déploiement de PVS-Studio, notamment dans les services cloud. Pour ne pas aller loin, vérifions le code source de Chocolatey. Azure DevOps servira de systÚme CI.
Voici une liste de nos autres articles sur l'intégration avec des systÚmes cloud :
Je vous conseille de prĂȘter attention au premier article sur l'intĂ©gration avec Azure DevOps, car certains points y sont omis pour Ă©viter les doublons.
Ainsi, les héros de cet article sont :
â un outil d'analyse statique du code, conçu pour identifier les erreurs et les vulnĂ©rabilitĂ©s potentielles dans des programmes Ă©crits en C, C++, C# et Java. Il fonctionne sur des systĂšmes 64 bits sous Windows, Linux et macOS, et peut analyser du code destinĂ© aux plateformes ARM 32 bits, 64 bits et embarquĂ©es. Si vous essayez l'analyse statique du code pour la premiĂšre fois sur vos projets, nous vous recommandons de consulter sur la façon de visualiser rapidement les avertissements intĂ©ressants de PVS-Studio et d'Ă©valuer les capacitĂ©s de cet outil.
â un ensemble de services cloud qui couvre tout le processus de dĂ©veloppement. Cette plateforme comprend des outils tels que Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, et Azure Test Plans, permettant d'accĂ©lĂ©rer le processus de crĂ©ation de logiciels et d'en amĂ©liorer la qualitĂ©.
â un gestionnaire de paquets open source pour Windows. L'objectif du projet est d'automatiser l'ensemble du cycle de vie des logiciels, de l'installation Ă la mise Ă jour et Ă la suppression, sous les systĂšmes d'exploitation Windows.
Sur l'utilisation de Chocolatey
Vous pouvez voir comment installer le gestionnaire de paquets lui-mĂȘme Ă partir de cette . La documentation complĂšte sur l'installation de l'analyseur est disponible dans la section « Installation Ă l'aide du gestionnaire de paquets Chocolatey ». Je vais briĂšvement rappeler certains points de lĂ -bas.
Commande pour installer la derniĂšre version de l'analyseur :
choco install pvs-studioCommande pour installer une version spécifique du paquet PVS-Studio :
choco install pvs-studio --version=7.05.35617.2075Par dĂ©faut, seul le noyau de l'analyseur - le composant Core - est installĂ©. Tous les autres indicateurs (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) peuvent ĂȘtre passĂ©s Ă l'aide de âpackage-parameters.
Voici un exemple de commande qui installera l'analyseur avec le plugin pour Visual Studio 2019 :
choco install pvs-studio --package-parameters="'\/MSVS2019'"Voyons maintenant un exemple d'utilisation pratique de l'analyseur sous Azure DevOps.
Configuration
Je rappelle que des points comme l'enregistrement d'un compte, la création d'un pipeline de construction et la synchronisation du compte avec le projet dans le dépÎt sur GitHub sont abordés dans un document séparé. . Notre configuration commencera directement par l'écriture du fichier de configuration.
Pour commencer, configurons le déclencheur d'exécution en indiquant que nous ne lançons que pour les modifications dans master la branche :
trigger:
- masterEnsuite, 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 steps). Bien qu'il ne soit pas possible d'installer des logiciels arbitraires sur la machine virtuelle, je n'ai pas ajoutĂ© de conteneur Docker. Nous pouvons ajouter Chocolatey en tant qu'extension pour Azure DevOps. Pour cela, allons Ă . Cliquez sur Get it free. Ensuite, si vous ĂȘtes dĂ©jĂ connectĂ©, il vous suffit de choisir votre compte, sinon, suivez la mĂȘme procĂ©dure aprĂšs vous ĂȘtre connectĂ©.

Ici, vous devez choisir oĂč nous ajouterons l'extension, puis appuyer sur le bouton Installer.

AprÚs l'installation réussie, cliquons sur Proceed to organization:

Vous pouvez maintenant voir le modĂšle de tĂąche Chocolatey dans la fenĂȘtre tasks lors de l'Ă©dition du fichier de configuration azure-pipelines.yml :

Cliquons sur Chocolatey et verrons la liste des champs :

Ici, nous devons sélectionner install dans le champ des commandes. Dans Nuspec File Name nous spécifions le nom du package souhaité - pvs-studio. Si nous ne spécifions pas de version, c'est la derniÚre qui sera installée, ce qui nous convient parfaitement. Cliquons sur le bouton add et nous verrons la tùche généré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. Elles stockeront le login et la clĂ© de licence de PVS-Studio. Pour dĂ©finir leurs valeurs, ouvrons le menu Variables->New variable. CrĂ©ons des variables PVSNAME pour le login et PVSKEY pour la clĂ© de l'analyseur. N'oubliez pas de cocher la case Gardez cette valeur secrĂšte pour PVSKEY. Code de la commande :
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials
âu $(PVSNAME) ân $(PVSKEY)Nous allons rassembler le projet Ă l'aide du fichier bat situĂ© dans le rĂ©fĂ©rentiel :
call build.batCrĂ©ons un dossier oĂč seront stockĂ©s les fichiers contenant les rĂ©sultats du travail de l'analyseur :
call mkdir PVSTestResultsLançons l'analyse du projet :
call "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe"
ât .srcchocolatey.sln âo .PVSTestResultsChoco.plog Convertissons notre rapport au format html en utilisant l'utilitaire PlogConverter :
call "C:Program Files (x86)PVS-StudioPlogConverter.exe"
ât html âo PVSTestResults .PVSTestResultsChoco.plogNous devons 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-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()Cliquez sur Enregistrer->Enregistrer->Exécuter pour exécuter la tùche. Nous téléchargerons le rapport en accédant à l'onglet des tùches.
Le projet Chocolatey contient un total de 37615 lignes de code C#. Examinons certaines des erreurs trouvées.
Résultats de l'analyse
Avertissement N1
Avertissement de l'analyseur : La variable âProviderâ est assignĂ©e Ă elle-mĂȘme. CrytpoHashProviderSpecs.cs 38
public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
....
protected CryptoHashProvider Provider;
....
public override void Context()
{
Provider = Provider = new CryptoHashProvider(FileSystem.Object);
}
}L'analyseur a dĂ©tectĂ© qu'une variable est assignĂ©e Ă elle-mĂȘme, ce qui n'a pas de sens. Il est probable qu'Ă la place de l'une de ces variables, une autre devrait ĂȘtre utilisĂ©e. Ou alors, c'est une faute de frappe, et l'assignation superflue peut tout simplement ĂȘtre supprimĂ©e.
Avertissement N2
Avertissement de l'analyseur : [CWE-480] L'opĂ©rateur â&â Ă©value les deux opĂ©randes. Peut-ĂȘtre qu'un opĂ©rateur â&&â Ă court-circuit devrait ĂȘtre utilisĂ© Ă la place. 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;
}
}La diffĂ©rence entre l'opĂ©rateur & et l'opĂ©rateur && rĂ©side dans le fait que si la partie gauche de l'expression â faux, cela calculera tout de mĂȘme la partie droite, ce qui dans ce cas implique des appels de mĂ©thode inutiles. system.directory_exists.
Dans le fragment examinĂ©, c'est un petit dĂ©tail. 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'a aucune influence. Cependant, dans d'autres cas, la confusion entre & et && peut provoquer de graves problĂšmes lorsque la partie droite de l'expression traite des valeurs incorrectes ou non autorisĂ©es. Par exemple, dans notre collection d'erreurs, , il y a ce 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 du tableau. Cela gĂ©nĂ©rera une exception IndexOutOfRangeException.
Avertissements N3, N4
Avertissement de l'analyseur : [CWE-571] L'expression âshortPromptâ est toujours vraie. InteractivePrompt.cs 101
Avertissement de l'analyseur : [CWE-571] L'expression âshortPromptâ est toujours vraie. 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
....
}
....
}Dans ce cas, il y a une logique Ă©trange dans le fonctionnement de l'opĂ©rateur ternaire. Examinons plus en dĂ©tail : si la condition marquĂ©e par le chiffre 1 se rĂ©alise, nous passerons Ă la condition 2, qui est toujours true, ce qui signifie que la ligne 3 sera exĂ©cutĂ©e. Si la condition 1 s'avĂšre fausse, nous passerons Ă la ligne marquĂ©e par le chiffre 4, dont la condition est Ă©galement toujours true, ce qui signifie que la ligne 5 sera exĂ©cutĂ©e. Ainsi, les conditions marquĂ©es par le commentaire 0 ne seront jamais exĂ©cutĂ©es, ce qui peut ne pas correspondre Ă la logique que le programmeur avait en tĂȘte.
Avertissement N5
Avertissement de l'analyseur : [CWE-783] Peut-ĂȘtre que l'opĂ©rateur â?:â fonctionne diffĂ©remment de ce qui Ă©tait attendu. Sa prioritĂ© est infĂ©rieure Ă celle d'autres opĂ©rateurs dans sa condition. 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);
}
}Le diagnostic a été déclenché sur la ligne :
while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)Ătant donnĂ© que la variable j plus haut, il est initialisĂ© Ă zĂ©ro, l'opĂ©rateur ternaire retournera une valeur faux. En raison de cette condition, le corps de la boucle ne s'exĂ©cutera qu'une seule fois. Je pense que ce fragment de code fonctionne tout Ă fait diffĂ©remment de ce que le programmeur avait prĂ©vu.
Avertissement N6
Avertissement de l'analyseur : [CWE-571] L'expression 'installedPackageVersions.Count != 1' est toujours vraie. NugetService.cs 1405
private void remove_nuget_cache_for_package(....)
{
if (!config.AllVersions && installedPackageVersions.Count > 1)
{
const string allVersionsChoice = "Toutes versions";
if (installedPackageVersions.Count != 1)
{
choices.Add(allVersionsChoice);
}
....
}
....
}Il y a une condition imbriquée étrange ici : installedPackageVersions.Count != 1, qui sera toujours true. Souvent, ce genre d'avertissement signale une erreur logique dans le code, ou parfois juste une vérification redondante.
Avertissement N7
Avertissement de l'analyseur : Il y a des sous-expressions identiques 'commandArguments.contains("-apikey")' à gauche et à droite de l'opérateur '||'. 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");
}Le programmeur qui a Ă©crit ce bout de code a copiĂ©-collĂ© les deux derniĂšres lignes et a oubliĂ© de les modifier. En consĂ©quence, les utilisateurs de Chocolatey n'ont pas pu appliquer le paramĂštre apikey d'autres maniĂšres Ă©galement. De la mĂȘme maniĂšre que les paramĂštres ci-dessus, je peux proposer les options suivantes :
commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");Les erreurs de copie-coller ont de grandes chances d'apparaĂźtre tĂŽt ou tard dans tout projet avec beaucoup de code source, et l'un des meilleurs moyens de lutter contre cela est l'analyse statique.
P.S. Et comme toujours, cette erreur a tendance Ă apparaĂźtre Ă la fin d'une condition multi-ligne :). Voir la publication "".
Avertissement N8
Avertissement de l'analyseur : [CWE-476] L'objet 'installedPackage' a été utilisé avant d'avoir été vérifié contre null. Vérifiez les lignes : 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)
{
....
}
....
}Erreur classique : l'objet est utilisĂ© avant d'ĂȘtre vĂ©rifiĂ© installedPackage Cela indique l'une des deux problĂšmes dans le programme : soit nulln'est jamais Ă©gal Ă installedPackage , ce qui est douteux, et donc la vĂ©rification est superflue, soit nous pouvons potentiellement rencontrer une grave erreur dans le code â une tentative d'accĂšs par un pointeur nul. nullVoilĂ , nous avons encore fait un petit pas â utiliser PVS-Studio est devenu encore plus simple et pratique. Je tiens Ă©galement Ă dire que Chocolatey est un bon gestionnaire de paquets avec peu d'erreurs dans le code, qui pourraient encore diminuer avec l'utilisation de PVS-Studio.
Conclusion
et essayez PVS-Studio. L'utilisation réguliÚre de l'analyseur statique améliorera la qualité et la fiabilité du code développé par votre équipe et aidera à prévenir de nombreuses
Nous vous invitons vulnérabilités de type zero-day .
P.S.
PVS-Studio est maintenant intégré à Chocolatey : Vérification de Chocolatey sous Azure DevOps
Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien vers la traduction : Vladislav Stolyarov. .
Source : habr.com
