PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps
Seguimos facendo que o uso de PVS-Studio sexa máis cómodo. O noso analizador xa está dispoñible en Chocolatey, un xestor de paquetes para Windows. Cremos que isto facilitará a implantación de PVS-Studio, en particular, nos servizos na nube. Para non ir lonxe, comprobemos o código fonte do mesmo Chocolatey. Azure DevOps actuará como un sistema CI.

Aquí tes unha lista dos nosos outros artigos sobre o tema da integración con sistemas de nube:

Aconséllovos que prestes atención ao primeiro artigo sobre a integración con Azure DevOps, xa que neste caso omítense algúns puntos para non duplicarse.

Entón, os heroes deste artigo:

PVS-Estudio é unha ferramenta de análise de código estático deseñada para identificar erros e posibles vulnerabilidades en programas escritos en C, C++, C# e Java. Funciona en sistemas Windows, Linux e macOS de 64 bits e pode analizar código deseñado para plataformas ARM de 32, 64 bits e incorporadas. Se é a primeira vez que probas a análise de código estático para comprobar os teus proxectos, recomendámosche que te familiarices artigo sobre como ver rapidamente os avisos de PVS-Studio máis interesantes e avaliar as capacidades desta ferramenta.

Azure DevOps — un conxunto de servizos na nube que cobren conxuntamente todo o proceso de desenvolvemento. Esta plataforma inclúe ferramentas como Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, que permiten acelerar o proceso de creación de software e mellorar a súa calidade.

Chocolatey é un xestor de paquetes de código aberto para Windows. O obxectivo do proxecto é automatizar todo o ciclo de vida do software desde a instalación ata a actualización e desinstalación nos sistemas operativos Windows.

Sobre o uso de Chocolatey

Podes ver como instalar o propio xestor de paquetes neste Ligazón. A documentación completa para a instalación do analizador está dispoñible en Ligazón Vexa a sección Instalación usando o xestor de paquetes Chocolatey. A partir de aí, repetirei brevemente algúns puntos.

Comando para instalar a última versión do analizador:

choco install pvs-studio

Comando para instalar unha versión específica do paquete PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Por defecto, só está instalado o núcleo do analizador, o compoñente Core. Todas as outras marcas (autónomos, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) pódense pasar usando --package-parameters.

Un exemplo dun comando que instalará un analizador cun complemento para Visual Studio 2019:

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

Agora vexamos un exemplo de uso cómodo do analizador en Azure DevOps.

axuste

Permíteme recordarche que hai unha sección separada sobre cuestións como rexistrar unha conta, crear un Build Pipeline e sincronizar a túa conta cun proxecto situado no repositorio de GitHub. artigo. A nosa configuración comezará inmediatamente coa escritura dun ficheiro de configuración.

En primeiro lugar, imos configurar un disparador de lanzamento, indicando que o lanzamos só para cambios en mestre rama:

trigger:
- master

A continuación temos que seleccionar unha máquina virtual. Polo momento será un axente aloxado por Microsoft con Windows Server 2019 e Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Pasemos ao corpo do ficheiro de configuración (block pasos). A pesar de que non pode instalar software arbitrario nunha máquina virtual, non engadín un contedor Docker. Podemos engadir Chocolatey como extensión para Azure DevOps. Para iso, imos a Ligazón. Fai clic Conséguelo gratis. A continuación, se xa estás autorizado, simplemente selecciona a túa conta e, se non, fai o mesmo despois da autorización.

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Aquí cómpre seleccionar onde engadiremos a extensión e facer clic no botón Instalar.

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Despois da instalación exitosa, fai clic Proceder á organización:

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Agora podes ver o modelo para a tarefa Chocolatey na xanela tarefas ao editar un ficheiro de configuración azure-pipelines.yml:

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Fai clic en Chocolatey e mira unha lista de campos:

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Aquí temos que seleccionar instalar no campo cos equipos. EN Nome do ficheiro Nuspec indica o nome do paquete necesario: pvs-studio. Se non especificas a versión, instalarase a última, que nos convén completamente. Prememos o botón engadir e veremos a tarefa xerada no ficheiro de configuración.

steps:
- task: ChocolateyCommand@0
  inputs:
    command: 'install'
    installPackageId: 'pvs-studio'

A continuación, imos pasar á parte principal do noso ficheiro:

- task: CmdLine@2
  inputs:
    script: 

Agora necesitamos crear un ficheiro coa licenza do analizador. Aquí PVSNAME и PVSKEY – nomes de variables cuxos valores especificamos na configuración. Almacenarán o inicio de sesión e a clave de licenza de PVS-Studio. Para establecer os seus valores, abra o menú Variables->Nova variable. Imos crear variables PVSNAME para iniciar sesión e PVSKEY para a chave do analizador. Non esquezas marcar a caixa Mantén este valor en segredo para PVSKEY. Código de comando:

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

Imos construír o proxecto usando o ficheiro bat situado no repositorio:

сall build.bat

Imos crear un cartafol onde se almacenarán os ficheiros cos resultados do analizador:

сall mkdir PVSTestResults

Comezamos a analizar o proxecto:

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

Convertemos o noso informe ao formato html usando a utilidade PlogСonverter:

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

Agora cómpre crear unha tarefa para poder cargar o informe.

- task: PublishBuildArtifacts@1
  inputs:
    pathToPublish: PVSTestResults
    artifactName: PVSTestResults
    condition: always()

O ficheiro de configuración completo ten o seguinte aspecto:

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()

Prememos Gardar->Gardar->Executar para executar a tarefa. Descarguemos o informe indo á pestana de tarefas.

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

O proxecto Chocolatey contén só 37615 liñas de código C#. Vexamos algúns dos erros atopados.

Resultados da proba

Aviso N1

Aviso do analizador: V3005 A variable "Proveedor" está asignada a si mesma. CrytpoHashProviderSpecs.cs 38

public abstract class CrytpoHashProviderSpecsBase : TinySpec
{
  ....
  protected CryptoHashProvider Provider;
  ....
  public override void Context()
  {
    Provider = Provider = new CryptoHashProvider(FileSystem.Object);
  }
}

O analizador detectou unha asignación da variable a si mesmo, que non ten sentido. O máis probable é que en lugar dunha destas variables haxa outra. Ben, ou isto é un erro tipográfico e simplemente pódese eliminar a tarefa extra.

Aviso N2

Aviso do analizador: V3093 [CWE-480] O operador '&' avalía ambos os operandos. Quizais debería utilizarse no seu lugar un operador de curtocircuíto "&&". Plataforma.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;
  }
}

Diferenza de operador & do operador && é que se o lado esquerdo da expresión é teito, entón aínda se calculará o lado dereito, o que neste caso implica chamadas de método innecesarias sistema.directorio_existe.

No fragmento considerado, trátase dunha falla menor. Si, esta condición pódese optimizar substituíndo o operador & polo operador &&, pero dende un punto de vista práctico, isto non afecta a nada. Non obstante, noutros casos, a confusión entre & e && pode causar serios problemas cando o lado dereito da expresión é tratado con valores incorrectos/inválidos. Por exemplo, na nosa colección de erros, identificado mediante o diagnóstico V3093, existe este caso:

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

Aínda que o índice k é incorrecto, empregarase para acceder a un elemento da matriz. Como resultado, lanzarase unha excepción IndexOutOfRangeException.

Avisos N3, N4

Aviso do analizador: V3022 [CWE-571] A expresión 'shortPrompt' sempre é verdadeira. InteractivePrompt.cs 101
Aviso do analizador: V3022 [CWE-571] A expresión 'shortPrompt' sempre é verdadeira. 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
    ....
  }
  ....
}

Neste caso, hai unha estraña lóxica detrás do funcionamento do operador ternario. Vexamos máis de cerca: se se cumpre a condición que marquei co número 1, pasaremos á condición 2, que sempre é certo, o que significa que se executará a liña 3. Se a condición 1 resulta ser falsa, imos á liña marcada co número 4, a condición na que tamén está sempre certo, o que significa que se executará a liña 5. Así, nunca se cumprirán as condicións marcadas co comentario 0, o que pode non ser exactamente a lóxica de funcionamento que esperaba o programador.

Aviso N5

Aviso do analizador: V3123 [CWE-783] Quizais o operador '?:' funcione dun xeito diferente do que se esperaba. A súa prioridade é inferior á do resto de operadores na súa condición. Opcións.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);
  }
}

O diagnóstico funcionou para a liña:

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

Xa que a variable j unhas liñas anteriores iníciase a cero, o operador ternario devolverá o valor teito. Debido a esta condición, o corpo do bucle executarase só unha vez. Paréceme que este anaco de código non funciona en absoluto como pretendía o programador.

Aviso N6

Aviso do analizador: V3022 [CWE-571] A expresión 'installedPackageVersions.Count != 1' sempre é verdadeira. 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);
    }
    ....
  }
  ....
}

Aquí hai unha estraña condición aniñada: installPackageVersions.Count != 1que sempre será certo. Moitas veces, tal aviso indica un erro lóxico no código e noutros casos simplemente indica unha comprobación redundante.

Aviso N7

Aviso do analizador: V3001 Hai subexpresións idénticas 'commandArguments.contains("-apikey")' á esquerda e á dereita do '||' operador. 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");
}

O programador que escribiu esta sección de código copiou e pegou as dúas últimas liñas e esqueceuse de editalas. Debido a isto, os usuarios de Chocolatey non puideron aplicar o parámetro apikey un par de formas máis. Semellante aos parámetros anteriores, podo ofrecer as seguintes opcións:

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

Os erros de copiar e pegar teñen unha gran probabilidade de aparecer tarde ou cedo en calquera proxecto cunha gran cantidade de código fonte, e unha das mellores ferramentas para combatelos é a análise estática.

PD E como sempre, este erro adoita aparecer ao final dunha condición de varias liñas :). Ver publicación "Efecto de última liña".

Aviso N8

Aviso do analizador: V3095 [CWE-476] O obxecto 'installedPackage' utilizouse antes de verificalo contra nulo. Liñas de verificación: 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)
  {
    ....
  }
  ....
}

Erro clásico: primeiro o obxecto Paquete instalado úsase e despois comproba nulo. Este diagnóstico indícanos un dos dous problemas do programa: calquera dos dous Paquete instalado nunca igual nulo, que é dubidoso, e entón a comprobación é redundante, ou poderíamos ter un erro grave no código: un intento de acceder a unha referencia nula.

Conclusión

Así que demos outro pequeno paso: agora usar PVS-Studio volveuse aínda máis fácil e cómodo. Tamén me gustaría dicir que Chocolatey é un bo xestor de paquetes cun pequeno número de erros no código, que poderían ser aínda menos cando se usa PVS-Studio.

Convidámolo descargar e proba PVS-Studio. O uso regular dun analizador estático mellorará a calidade e a fiabilidade do código que desenvolve o teu equipo e axudará a previr moitos vulnerabilidades de día cero.

PS

Antes da publicación, enviamos o artigo aos desenvolvedores de Chocolatey, e recibiron ben. Non atopamos nada crítico, pero a eles, por exemplo, gustoulles o erro que atopamos relacionado coa clave "api-key".

PVS-Studio está agora en Chocolatey: comprobando Chocolatey desde Azure DevOps

Se queres compartir este artigo cun público de fala inglesa, utiliza a ligazón de tradución: Vladislav Stolyarov. PVS-Studio está agora en Chocolatey: comprobando Chocolatey baixo Azure DevOps.

Fonte: www.habr.com

Engadir un comentario