PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps
Продължаваме да правим използването на PVS-Studio по-удобно. Нашият анализатор вече е наличен в Chocolatey, мениджър на пакети за Windows. Вярваме, че това ще улесни внедряването на PVS-Studio, по-специално в облачните услуги. За да не отидем далеч, нека проверим изходния код на същия Chocolatey. Azure DevOps ще действа като CI система.

Ето списък с други наши статии по темата за интеграция с облачни системи:

Съветвам ви да обърнете внимание на първата статия за интеграцията с Azure DevOps, тъй като в този случай някои точки са пропуснати, за да не се дублират.

И така, героите на тази статия:

PVS-Студио е инструмент за анализ на статичен код, предназначен да идентифицира грешки и потенциални уязвимости в програми, написани на C, C++, C# и Java. Работи на 64-битови Windows, Linux и macOS системи и може да анализира код, предназначен за 32-битови, 64-битови и вградени ARM платформи. Ако за първи път се опитвате да анализирате статичен код, за да проверите вашите проекти, препоръчваме ви да се запознаете с статия за това как бързо да видите най-интересните предупреждения на PVS-Studio и да оцените възможностите на този инструмент.

Azure DevOps — набор от облачни услуги, които съвместно покриват целия процес на разработка. Тази платформа включва инструменти като Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, които ви позволяват да ускорите процеса на създаване на софтуер и да подобрите качеството му.

шоколадово е мениджър на пакети с отворен код за Windows. Целта на проекта е да автоматизира целия жизнен цикъл на софтуера от инсталирането до актуализирането и деинсталирането на операционни системи Windows.

Относно използването на Chocolatey

Можете да видите как да инсталирате самия мениджър на пакети тук връзка. Пълната документация за инсталиране на анализатора е достъпна на връзка Вижте раздела Инсталиране с помощта на мениджъра на пакети Chocolatey. Накратко ще повторя някои точки оттам.

Команда за инсталиране на най-новата версия на анализатора:

choco install pvs-studio

Команда за инсталиране на конкретна версия на пакета PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

По подразбиране е инсталирано само ядрото на анализатора, компонентът Core. Всички други флагове (Standalone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) могат да бъдат предадени чрез --package-parameters.

Пример за команда, която ще инсталира анализатор с плъгин за Visual Studio 2019:

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

Сега нека да разгледаме пример за удобно използване на анализатора под Azure DevOps.

регулиране

Нека ви напомня, че има отделен раздел за такива въпроси като регистриране на акаунт, създаване на Build Pipeline и синхронизиране на вашия акаунт с проект, намиращ се в хранилището на GitHub. статия. Нашата настройка веднага ще започне с писане на конфигурационен файл.

Първо, нека настроим тригер за стартиране, който показва, че стартираме само за промени в майстор клон:

trigger:
- master

След това трябва да изберем виртуална машина. Засега това ще бъде хостван от Microsoft агент с Windows Server 2019 и Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Нека да преминем към тялото на конфигурационния файл (блок стъпки). Въпреки факта, че не можете да инсталирате произволен софтуер във виртуална машина, аз не добавих Docker контейнер. Можем да добавим Chocolatey като разширение за Azure DevOps. За да направите това, нека отидем на връзка. Кликнете Вземи безплатно. След това, ако вече сте упълномощени, просто изберете вашия акаунт, а ако не, направете същото след упълномощаване.

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Тук трябва да изберете къде ще добавим разширението и да щракнете върху бутона инсталирам.

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

След успешна инсталация щракнете Пристъпете към организация:

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Вече можете да видите шаблона за задачата Chocolatey в прозореца задачи когато редактирате конфигурационен файл azure-pipelines.yml:

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Кликнете върху Chocolatey и вижте списък с полета:

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Тук трябва да изберем инсталирам на полето с екипите. IN Име на файл Nuspec посочете името на необходимия пакет – pvs-studio. Ако не посочите версията, ще бъде инсталирана най-новата, което ни устройва напълно. Да натиснем бутона добавете и ще видим генерираната задача в конфигурационния файл.

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

След това нека преминем към основната част на нашия файл:

- task: CmdLine@2
  inputs:
    script: 

Сега трябва да създадем файл с лиценза на анализатора. Тук PVSNAME и PVSKEY – имена на променливи, чиито стойности задаваме в настройките. Те ще съхраняват данните за вход и лицензния ключ на PVS-Studio. За да зададете техните стойности, отворете менюто Променливи->Нова променлива. Нека създадем променливи PVSNAME за влизане и PVSKEY за ключа на анализатора. Не забравяйте да поставите отметка в квадратчето Пазете тази стойност в тайна за PVSKEY. Код на командата:

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

Нека изградим проекта с помощта на bat файла, намиращ се в хранилището:

сall build.bat

Нека създадем папка, в която ще се съхраняват файлове с резултатите от анализатора:

сall mkdir PVSTestResults

Нека започнем да анализираме проекта:

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

Преобразуваме нашия отчет в html формат с помощта на помощната програма PlogСonverter:

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

Сега трябва да създадете задача, за да можете да качите отчета.

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

Пълният конфигурационен файл изглежда така:

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

Да щракнем Запиши->Запиши->Изпълни за изпълнение на задачата. Нека изтеглим отчета, като отидем в раздела задачи.

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Проектът Chocolatey съдържа само 37615 реда C# код. Нека да разгледаме някои от откритите грешки.

Резултати от тестовете

Предупреждение N1

Предупреждение на анализатора: V3005 Променливата „Доставчик“ се присвоява сама на себе си. CrytpoHashProviderSpecs.cs 38

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

Анализаторът откри присвояване на променливата на себе си, което няма смисъл. Най-вероятно на мястото на една от тези променливи трябва да има друга. Е, или това е печатна грешка и допълнителното задание може просто да бъде премахнато.

Предупреждение N2

Предупреждение на анализатора: V3093 [CWE-480] Операторът „&“ оценява и двата операнда. Може би вместо това трябва да се използва оператор за късо съединение '&&'. 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;
  }
}

Операторска разлика & от оператора && е, че ако лявата страна на израза е фалшив, тогава дясната страна все още ще бъде изчислена, което в този случай предполага ненужни извиквания на метод system.directory_exists.

В разглеждания фрагмент това е незначителен недостатък. Да, това условие може да се оптимизира чрез замяна на оператора & с оператора &&, но от практическа гледна точка това не влияе на нищо. В други случаи обаче объркването между & и && може да причини сериозни проблеми, когато дясната страна на израза се третира с неправилни/невалидни стойности. Например в нашата колекция от грешки, идентифицирани с помощта на диагностика V3093, има такъв случай:

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

Дори ако индексът k е неправилно, ще се използва за достъп до елемент от масив. В резултат на това ще бъде хвърлено изключение IndexOutOfRangeException.

Предупреждения N3, N4

Предупреждение на анализатора: V3022 [CWE-571] Изразът „shortPrompt“ винаги е верен. InteractivePrompt.cs 101
Предупреждение на анализатора: V3022 [CWE-571] Изразът „shortPrompt“ винаги е верен. 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
    ....
  }
  ....
}

В този случай има странна логика зад работата на троичния оператор. Нека разгледаме по-отблизо: ако условието, което маркирах с номер 1, е изпълнено, тогава ще преминем към условие 2, което винаги е вярно, което означава, че ще бъде изпълнен ред 3. Ако условие 1 се окаже невярно, тогава ще преминем към реда, отбелязан с номер 4, условието в което също е винаги вярно, което означава, че ще бъде изпълнен ред 5. По този начин условията, отбелязани с коментар 0, никога няма да бъдат изпълнени, което може да не е точно логиката на работа, която програмистът е очаквал.

Предупреждение N5

Предупреждение на анализатора: V3123 [CWE-783] Може би операторът '?:' работи по начин, различен от очаквания. Неговият приоритет е по-нисък от приоритета на другите оператори в неговото състояние. 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);
  }
}

Диагностиката работи за линията:

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

Тъй като променливата j няколко реда по-горе се инициализира на нула, троичният оператор ще върне стойността фалшив. Поради това условие, тялото на цикъла ще бъде изпълнено само веднъж. Струва ми се, че тази част от кода изобщо не работи, както е предвидил програмистът.

Предупреждение N6

Предупреждение на анализатора: V3022 [CWE-571] Изразът 'installedPackageVersions.Count != 1' винаги е верен. 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);
    }
    ....
  }
  ....
}

Тук има странно вложено условие: InstallPackageVersions.Count != 1което винаги ще бъде вярно. Често такова предупреждение показва логическа грешка в кода, а в други случаи просто показва излишна проверка.

Предупреждение N7

Предупреждение на анализатора: V3001 Има идентични подизрази 'commandArguments.contains("-apikey")' отляво и отдясно на '||' оператор. 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");
}

Програмистът, който е написал тази част от кода, е копирал и поставил последните два реда и е забравил да ги редактира. Поради това потребителите на Chocolatey не успяха да приложат параметъра apikey още няколко начина. Подобно на параметрите по-горе, мога да предложа следните опции:

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

Грешките при копиране и поставяне имат голям шанс да се появят рано или късно във всеки проект с голямо количество изходен код и един от най-добрите инструменти за борба с тях е статичният анализ.

PS И както винаги, тази грешка има тенденция да се появява в края на многоредово условие :). Вижте публикацията "Ефект на последния ред".

Предупреждение N8

Предупреждение на анализатора: V3095 [CWE-476] Обектът „installedPackage“ е използван, преди да бъде проверен срещу null. Проверете редове: 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)
  {
    ....
  }
  ....
}

Класическа грешка: първо възразете инсталиран пакет се използва и след това се проверява за нула. Тази диагностика ни казва за един от двата проблема в програмата: или инсталиран пакет никога равни нула, което е съмнително и тогава проверката е излишна, или потенциално бихме могли да получим сериозна грешка в кода - опит за достъп до нулева препратка.

Заключение

Така че направихме още една малка стъпка - сега използването на PVS-Studio стана още по-лесно и удобно. Бих искал също да кажа, че Chocolatey е добър мениджър на пакети с малък брой грешки в кода, които могат да бъдат дори по-малко, когато използвате PVS-Studio.

каним ви изтеглите и опитайте PVS-Studio. Редовното използване на статичен анализатор ще подобри качеството и надеждността на кода, който вашият екип разработва, и ще помогне за предотвратяване на много уязвимости от нулевия ден.

PS

Преди публикуването изпратихме статията на разработчиците на Chocolatey и те я приеха добре. Не намерихме нищо критично, но те например харесаха грешката, която открихме, свързана с ключа „api-key“.

PVS-Studio вече е в Chocolatey: проверка на Chocolatey от под Azure DevOps

Ако искате да споделите тази статия с англоезична аудитория, моля, използвайте връзката за превод: Владислав Столяров. PVS-Studio вече е в Chocolatey: Проверка на Chocolatey под Azure DevOps.

Източник: www.habr.com

Добавяне на нов коментар