PVS-Studio ahora está en Chocolatey:comprobando Chocolatey en Azure DevOps

 C Programming >> Programación C >  >> Tags >> Azure
PVS-Studio ahora está en Chocolatey:comprobando Chocolatey en Azure DevOps

Seguimos haciendo más cómodo el uso de PVS-Studio. Nuestro analizador ya está disponible en Chocolatey, el administrador de paquetes de Windows. Creemos que esto facilitará la implementación de PVS-Studio, particularmente en servicios en la nube. Entonces, de inmediato, también verificamos el código fuente del mismo Chocolatey. Azure DevOps asumió el papel del sistema de CI.

Esta es la lista de nuestros otros artículos sobre integración en la nube:

  • PVS-Studio en las nubes:Azure DevOps
  • PVS-Studio en las nubes:CircleCI
  • PVS-Estudio en las nubes:Travis CI
  • PVS-Studio en las nubes:GitLab CI/CD

Le sugiero que preste atención al primer artículo sobre la integración con Azure DevOps, ya que se omitirán algunos puntos para evitar repetir algunos matices.

Entonces, los personajes principales de este artículo son:

PVS-Studio es un analizador de código estático para detectar errores y posibles vulnerabilidades en el código fuente de los programas, escrito en C, C++, C# y Java. Funciona en sistemas de 64 bits en Windows, Linux y macOS y puede analizar código para plataformas ARM integradas y de 32 bits, 64 bits. Si es la primera vez que va a probar el análisis de código estático para comprobar sus proyectos, le recomendamos que lea el artículo sobre cómo comprobar rápidamente las advertencias más interesantes de PVS-Studio y evaluar las capacidades de esta herramienta.

Azure DevOps es un conjunto de servicios en la nube que cubren de forma conjunta todo el proceso de desarrollo. Esta plataforma incluye herramientas como Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans para acelerar el proceso de creación de software y mejorar su calidad.

Chocolatey es un administrador de paquetes de código abierto para Windows. El objetivo del proyecto es automatizar todo el ciclo de vida del software desde la instalación hasta la actualización y eliminación en los sistemas operativos Windows.

Acerca del uso de Chocolatey

Para ver cómo instalar el administrador de paquetes, siga este enlace. La documentación completa sobre la instalación del analizador está disponible en el enlace de la sección "Instalación mediante el administrador de paquetes Chocolatey". En pocas palabras, repetiré algunos de los puntos de allí.

El comando para la instalación de la última versión del analizador:

choco install pvs-studio

El comando para la instalación de un paquete específico de PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

De forma predeterminada, solo se instala el núcleo del analizador, que es el componente principal. Todos los demás indicadores (Independiente, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) se pueden pasar mediante --paquete-parámetros.

Un ejemplo de un comando que instalará el analizador con el complemento para Visual Studio 2019:

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

Este es un ejemplo del uso conveniente del analizador en Azure DevOps.

Configuración

Permítame recordarle que el artículo mencionado anteriormente brinda toda la información necesaria sobre cosas como la creación de Build Pipeline y la sincronización de la cuenta con el proyecto en un repositorio de GitHub. En nuestro caso, la configuración comenzará directamente con la escritura de un archivo de configuración.

Para empezar, configuraremos un activador de inicio, lo que indica que solo ejecutaremos cambios en el maestro rama:

trigger:
- master

A continuación, debemos elegir una máquina virtual. En este punto, será un agente hospedado de Microsoft con Windows Server 2019 y Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Pasemos al cuerpo del archivo de configuración (los pasos bloquear). Aunque no puede instalar software aleatorio en una máquina virtual, no agregué un contenedor Docker. Podemos agregar Chocolatey como una extensión para Azure DevOps. Para hacer esto, siga el enlace. Selecciona Obténlo gratis . Además, si ya ha iniciado sesión, simplemente elija su cuenta y, si no, haga lo mismo después de la autorización.

Aquí debemos elegir dónde agregar la extensión y hacer clic en Instalar .

Después de una instalación exitosa, haga clic en Continuar con la organización :

Ahora puedes ver la plantilla para la tarea Chocolatey en las tareas ventana al editar el archivo de configuración azure-pipelines.yml:

Haga clic en Chocolatey y verá la lista de campos:

Aquí tenemos que elegir instalar en el campo con comandos. En Nombre de archivo Nuspec , especifique el nombre del paquete necesario:pvs-studio. Sin especificación de versión, se instalará la última, lo cual es absolutamente genial para nosotros. Haz clic en añadir y ver la nueva tarea en el archivo de configuración.

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

A continuación, pasemos a la parte principal de nuestro archivo:

- task: CmdLine@2
  inputs:
    script:

Ahora necesitamos crear un archivo con la licencia del analizador. Aquí PVSNAME y PVSKEY son los nombres de las variables que especificamos en la configuración. Almacenarán el inicio de sesión y la clave de licencia de PVS-Studio. Para establecer sus valores, abra el menú Variables->Nueva variable . Luego cree variables:PVSNAME - para el inicio de sesión, y PVSKEY- para la clave del analizador. No olvide marcar Mantener este valor en secreto para PVSKEY . El código de comando:

call "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials 
–u $(PVSNAME) –n $(PVSKEY)

Cree el proyecto utilizando el archivo bat del repositorio.

call build.bat

Después de eso, cree el repositorio de archivos con los resultados del analizador:

 call mkdir PVSTestResults

A continuación, ejecute el análisis del proyecto.

call "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" 
–t .\src\chocolatey.sln –o .\PVSTestResults\Choco.plog

Convierta el informe al formato html mediante la utilidad PlogConverter:

call "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" 
–t html –o \PVSTestResults\ .\PVSTestResults\Choco.plog

Ahora necesita crear una tarea para poder descargar el informe.

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

El archivo de configuración completo tiene este 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-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()

Haga clic en Guardar->Guardar->Ejecutar para ejecutar la tarea. Vaya a la pestaña de tareas y descargue el informe.

El proyecto Chocolatey contiene solo 37615 líneas de código C#. Consideremos algunos de los errores detectados.

Resultados del análisis

Advertencia N1

Advertencia del analizador:V3005 La variable 'Proveedor' se asigna a sí misma. CrytpoHashProviderSpecs.cs 38

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

El analizador ha detectado una asignación de variables a sí mismo, lo que no tiene sentido. Lo más probable es que otra variable debería haber estado aquí en lugar de una de estas. O es un error tipográfico, y la asignación adicional simplemente se puede eliminar.

Advertencia N2

Advertencia del analizador:V3093 [CWE-480] El operador '&' evalúa ambos operandos. Tal vez debería usarse un operador de cortocircuito '&&' en su lugar. 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;
  }
}

La diferencia entre y y && operadores es que si la parte izquierda de la expresión es falsa , la parte derecha se evaluará de todos modos si se usa &, lo que, en este caso, implica llamadas innecesarias a system.directory_exists método.

En el fragmento considerado, es un defecto menor. Sí, esta condición se puede optimizar reemplazando el operador &por &&, pero desde un punto de vista práctico, no afecta nada. Sin embargo, en otros casos, la confusión entre &y &&puede causar serios problemas, cuando la parte correcta de la expresión maneja valores incorrectos o no válidos. Por ejemplo, este es el caso de nuestra colección de errores detectados por el diagnóstico V3093:

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

Incluso si la k índice es incorrecto, se utilizará para acceder al elemento de matriz. Como resultado, IndexOutOfRangeException se generará.

Advertencias N3, N4

Advertencia del analizador:V3022 [CWE-571] La expresión 'shortPrompt' siempre es verdadera. InteractivoPrompt.cs 101

Advertencia del analizador:V3022 [CWE-571] La expresión 'shortPrompt' siempre es verdadera. InteractivoPrompt.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
    ....
  }
  ....
}

En este caso, la lógica del operador ternario es extraña. Vamos a echar un vistazo debajo del capó:si se cumple la condición que marqué con el número 1, pasamos a la condición 2, que siempre es verdadera , lo que significa que la línea 3 se ejecutará. Si la condición número 1 es falsa, saltaremos a la línea, marcada como 4; su condición también es siempre verdadera , lo que significa que la línea 5 se ejecutará. Por lo tanto, las condiciones marcadas con el comentario 0 nunca se ejecutarán, lo que puede no ser la lógica que deseaba el programador.

Advertencia N5

Advertencia del analizador:V3123 [CWE-783] Quizás el operador '?:' funciona de forma diferente a la esperada. Su prioridad es inferior a la prioridad de otros operadores en su condición. Opciones.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);
  }
}

El diagnóstico activado para la siguiente línea:

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

Desde la j la variable se inicializa en 0 unas pocas líneas antes, el operador ternario devolverá falso . Debido a esta condición, el cuerpo del ciclo se ejecutará solo una vez. Me parece que este fragmento de código no funciona de la forma prevista por el programador.

Advertencia N6

Advertencia del analizador:V3022 [CWE-571] La expresión 'installedPackageVersions.Count !=1' siempre es verdadera. 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);
    }
    ....
  }
  ....
}

La condición anidada installedPackageVersions.Count !=1 , que siempre es verdadero , es bastante dudoso. A menudo, una advertencia de este tipo indica un error lógico en el código, o simplemente una verificación redundante.

Advertencia N7

Advertencia del analizador:V3001 Hay subexpresiones idénticas 'commandArguments.contains("-apikey")' a la izquierda y a la derecha de '||' 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");
}

El programador que escribió esta sección del código copió las últimas dos líneas y olvidó editarlas. Debido a esto, los usuarios de Chocolatey no pudieron aplicar la apikey parámetro en un par de otras maneras. Al igual que con el parámetro anterior, puedo sugerir las siguientes opciones:

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

Los errores de copiar y pegar tienen una gran posibilidad de aparecer tarde o temprano en cualquier proyecto con una gran base de código fuente, y uno de los mejores medios para luchar contra ellos es el análisis estático.

PD Y como siempre, este error tiende a aparecer al final de la condición de varias líneas :). Ver la publicación "Efecto de última línea".

Advertencia N8

Advertencia del analizador:V3095 [CWE-476] El objeto 'installedPackage' se usó antes de que se verificara contra nulo. Verifique las líneas: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)
  {
    ....
  }
  ....
}

Un error clásico:primero el installedPackage se usa el objeto y luego se comprueba si hay null . Este diagnóstico nos informa sobre uno de los problemas en el programa:o bien installedPackage nunca es null (que es cuestionable) y la verificación es redundante, o podemos obtener un error grave en el código:un intento de acceder a una referencia nula.

Conclusión

Así que hemos dado otro pequeño paso:ahora usar PVS-Studio se ha vuelto aún más fácil y conveniente. También me gustaría señalar que Chocolatey es un excelente administrador de paquetes con una cantidad baja de errores de código que podrían haber sido incluso menores si se verificara con PVS-Studio.

Le invito a descargar y probar PVS-Studio. El uso regular del analizador estático mejorará la calidad y la confiabilidad del código que escriba y ayudará a prevenir muchas vulnerabilidades de día cero.

PD

Antes de publicar el artículo, enviamos uno a los desarrolladores de Chocolatey, que estaban bastante satisfechos con él. No hemos encontrado ningún error crítico allí, pero les gustó un error relacionado con "api-key", por ejemplo.