PVS-Studio est maintenant dans Chocolatey: vérification de Chocolatey à partir d'Azure DevOps

Figure 4

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.

Figure 2


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

Figure 5


AprÚs une installation réussie, cliquez sur Procéder à l'organisation :

Figure 9


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:

Figure 6


Cliquez sur Chocolatey et voyez une liste de champs:

Figure 7


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.

Figure 8



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 N1

Analyzer Avertissement: V3005 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 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 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 && 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, N4

Analyseur Avertissement: V3022 [CWE-571] L'expression 'shortPrompt' est toujours vraie. InteractivePrompt.cs 101
Avertissement de l'analyseur: V3022 [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 Ă©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 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 < 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 1405

private 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 N7

Analyzer Avertissement: V3001 Il existe des sous-expressions identiques 'commandArguments.contains ("- apikey")' à gauche et à droite de '||' 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 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 910

public 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 .

All Articles