PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps
Nous continuons à rendre l'utilisation de PVS-Studio plus pratique. Notre analyseur est désormais disponible dans Chocolatey, un gestionnaire de packages pour Windows. Nous pensons que cela facilitera le déploiement de PVS-Studio, notamment dans les services cloud. Pour ne pas aller loin, vérifions le code source du même Chocolatey. Azure DevOps agira comme un système CI.

Voici une liste de nos autres articles sur le thème de l’intégration avec les systèmes cloud :

Je vous conseille de faire attention au premier article sur l'intégration avec Azure DevOps, puisque dans ce cas certains points sont omis pour ne pas être dupliqués.

Alors, les héros de cet article :

PVS-Studio est un outil d'analyse de code statique conçu pour identifier les erreurs et les vulnérabilités potentielles dans les programmes écrits en C, C++, C# et Java. Fonctionne sur les systèmes Windows, Linux et macOS 64 bits et peut analyser le code conçu pour les plates-formes 32 bits, 64 bits et ARM 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 vous familiariser avec un article sur la façon de visualiser rapidement les avertissements PVS-Studio les plus intéressants et d'évaluer les capacités de cet outil.

DevOps Azure — un ensemble de services cloud qui couvrent conjointement l'ensemble du processus de développement. Cette plateforme comprend des outils tels que Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, qui vous permettent d'accélérer le processus de création de logiciels et d'améliorer sa qualité.

Chocolat est un gestionnaire de packages 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 désinstallation sur les systèmes d'exploitation Windows.

À propos de l'utilisation de Chocolatey

Vous pouvez voir comment installer le gestionnaire de paquets lui-même ici lien. La documentation complète pour l'installation de l'analyseur est disponible sur lien Voir la section Installation à l'aide du gestionnaire de packages Chocolatey. Je vais brièvement répéter quelques points à partir de là.

Commande pour installer la dernière version de l'analyseur :

choco install pvs-studio

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 cœur de l'analyseur, le composant Core, est installé. Tous les autres indicateurs (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) peuvent être transmis à l'aide de --package-parameters.

Un exemple de commande qui installera un analyseur avec un plugin pour Visual Studio 2019 :

choco install pvs-studio --package-parameters="'/MSVS2019'"

Examinons maintenant un exemple d'utilisation pratique de l'analyseur sous Azure DevOps.

réglage

Permettez-moi de vous rappeler qu'il existe une section distincte sur des questions telles que l'enregistrement d'un compte, la création d'un pipeline de build et la synchronisation de votre compte avec un projet situé dans le référentiel GitHub. article. Notre installation commencera immédiatement par l'écriture d'un fichier de configuration.

Tout d'abord, configurons un déclencheur de lancement, indiquant que nous lançons uniquement pour les changements de maître bifurquer:

trigger:
- master

Ensuite, nous devons sélectionner une machine virtuelle. Pour l'instant, il s'agira d'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 mesures). Malgré le fait que vous ne pouvez pas installer de logiciel arbitraire dans une machine virtuelle, je n'ai pas ajouté de conteneur Docker. Nous pouvons ajouter Chocolatey comme extension pour Azure DevOps. Pour ce faire, allons à lien. Cliquez sur Obtenir gratuitement. Ensuite, si vous êtes déjà autorisé, sélectionnez simplement votre compte, et sinon, faites la même chose après autorisation.

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Ici, vous devez sélectionner l'endroit où nous ajouterons l'extension et cliquer sur le bouton Installer.

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Après une installation réussie, cliquez sur Passer à l'organisation:

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Vous pouvez maintenant voir le modèle de la tâche Chocolatey dans la fenêtre tâches lors de la modification d'un fichier de configuration azure-pipelines.yml :

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Cliquez sur Chocolatey et voyez une liste de champs :

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Ici, nous devons sélectionner installer sur le terrain avec les équipes. DANS Nom du fichier Nuspec indiquez le nom du package requis – pvs-studio. Si vous ne précisez pas la version, la dernière version sera installée, ce qui nous convient tout à fait. Appuyons sur le bouton ajouter 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 ensuite à la partie principale de notre dossier :

- task: CmdLine@2
  inputs:
    script: 

Nous devons maintenant créer un fichier avec la licence de l'analyseur. Ici NOM PVS и PVSKEY – noms de variables dont nous précisons les valeurs dans les paramètres. Ils stockeront la connexion et la clé de licence PVS-Studio. Pour définir leurs valeurs, ouvrez le menu Variables->Nouvelle variable. Créons des variables NOM PVS pour vous connecter et PVSKEY pour la clé de l'analyseur. N'oubliez pas de cocher la case Gardez cette valeur secrète pour PVSKEY. Code de commande :

сall "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" credentials 
–u $(PVSNAME) –n $(PVSKEY)

Construisons le projet en utilisant le fichier bat situé dans le référentiel :

сall build.bat

Créons un dossier où seront stockés les fichiers avec les résultats de l'analyseur :

сall mkdir PVSTestResults

Commençons par analyser le projet :

сall "C:Program Files (x86)PVS-StudioPVS-Studio_Cmd.exe" 
–t .srcchocolatey.sln –o .PVSTestResultsChoco.plog 

Nous convertissons notre rapport au format html à l'aide de l'utilitaire PlogСonverter :

сall "C:Program Files (x86)PVS-StudioPlogConverter.exe" 
–t html –o PVSTestResults .PVSTestResultsChoco.plog

Vous devez maintenant créer une tâche pour 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()

Cliquons Enregistrer->Enregistrer->Exécuter pour exécuter la tâche. Téléchargeons le rapport en allant dans l'onglet tâches.

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Le projet Chocolatey ne contient que 37615 XNUMX lignes de code C#. Examinons quelques-unes des erreurs trouvées.

Résultats de test

Avertissement N1

Avertissement de l'analyseur : V3005 La variable 'Provider' est affecté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é une affectation de la variable à elle-même, ce qui n'a aucun sens. Très probablement, à la place de l’une de ces variables, il devrait y en avoir une autre. Eh bien, ou c'est une faute de frappe, et l'affectation supplémentaire peut simplement être supprimée.

Avertissement N2

Avertissement de l'analyseur : 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. Plateforme.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;
  }
}

Différence d'opérateur & de l'opérateur && c'est que si le côté gauche de l'expression est non, alors le côté droit sera toujours calculé, ce qui dans ce cas implique des appels de méthode inutiles system.directory_exists.

Dans le fragment considéré, 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 sérieux problèmes lorsque le côté droit de l'expression est traité avec des valeurs incorrectes/invalides. Par exemple, dans notre collection d'erreurs, identifié à l'aide du diagnostic V3093, il y a ce cas :

if ((k < nct) & (s[k] != 0.0))

Même si l'indice k est incorrect, il sera utilisé pour accéder à un élément du tableau. En conséquence, une exception sera levée IndexOutOfRangeException.

Avertissements N3, N4

Avertissement de l'analyseur : 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 derrière le fonctionnement de l’opérateur ternaire. Regardons de plus près : si la condition que j'ai marquée du chiffre 1 est remplie, alors nous passerons à la condition 2, qui est toujours oui, ce qui signifie que la ligne 3 sera exécutée. Si la condition 1 s'avère fausse, alors nous passerons à la ligne marquée du numéro 4, la condition dans laquelle est également toujours oui, ce qui signifie que la ligne 5 sera exécutée. Ainsi, les conditions marquées du commentaire 0 ne seront jamais remplies, ce qui peut ne pas être exactement la logique de fonctionnement attendue par le programmeur.

Avertissement N5

Avertissement de l'analyseur : V3123 [CWE-783] Peut-être que l'opérateur '?:' fonctionne 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);
  }
}

Le diagnostic a fonctionné pour la ligne :

while (start >= 0 && j != 0 ? description [j++ - 1] == '{' : false)

Puisque la variable j quelques lignes ci-dessus est initialisé à zéro, l'opérateur ternaire renverra la valeur non. A cause de cette condition, le corps de la boucle ne sera exécuté qu'une seule fois. Il me semble que ce morceau de code ne fonctionne pas du tout comme le programmeur l'avait prévu.

Avertissement N6

Avertissement de l'analyseur : 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);
    }
    ....
  }
  ....
}

Il y a une étrange condition imbriquée ici : installéPackageVersions.Count != 1qui sera toujours oui. Souvent, un tel avertissement indique une erreur logique dans le code et, dans d'autres cas, indique simplement une vérification redondante.

Avertissement N7

Avertissement de l'analyseur : V3001 Il y a des sous-expressions identiques 'commandArguments.contains("-apikey")' à gauche et à droite du '||' 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 cette section de code a copié et collé les deux dernières lignes et a oublié de les modifier. Pour cette raison, les utilisateurs de Chocolatey n'ont pas pu appliquer le paramètre clé API encore quelques façons. Semblable aux paramètres ci-dessus, je peux proposer les options suivantes :

commandArguments.contains("-apikey=");
commandArguments.contains("-api-key=");

Les erreurs de copier-coller ont de fortes chances d'apparaître tôt ou tard dans tout projet comportant une grande quantité de code source, et l'un des meilleurs outils pour les combattre est l'analyse statique.

PS Et comme toujours, cette erreur a tendance à apparaître à la fin d'une condition multiligne :). Voir publication "Effet de dernière ligne".

Avertissement N8

Avertissement de l'analyseur : 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 : l'objet d'abord package installé est utilisé puis vérifié nul. Ce diagnostic nous indique l'un des deux problèmes du programme : soit package installé jamais égal nul, ce qui est douteux, et alors la vérification est redondante, ou nous pourrions potentiellement avoir une erreur grave dans le code - une tentative d'accès à une référence nulle.

Conclusion

Nous avons donc franchi une nouvelle étape : utiliser PVS-Studio est devenu encore plus simple et pratique. Je voudrais également dire que Chocolatey est un bon gestionnaire de paquets avec un petit nombre d'erreurs dans le code, qui pourrait être encore moins lors de l'utilisation de PVS-Studio.

Nous invitons скачать et essayez 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 contribuera à prévenir de nombreux vulnérabilités du jour zéro.

PS

Avant la publication, nous avons envoyé l'article aux développeurs de Chocolatey, et ils l'ont bien reçu. Nous n'avons rien trouvé de critique, mais ils ont, par exemple, aimé le bug que nous avons trouvé lié à la clé « api-key ».

PVS-Studio est maintenant dans Chocolatey : vérification de Chocolatey sous Azure DevOps

Si vous souhaitez partager cet article avec un public anglophone, veuillez utiliser le lien de traduction : Vladislav Stolyarov. PVS-Studio est désormais dans Chocolatey : vérification de Chocolatey sous Azure DevOps.

Source: habr.com

Ajouter un commentaire