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. يعمل على أنظمة Windows وLinux وmacOS 64 بت، ويمكنه تحليل التعليمات البرمجية المصممة لمنصات ARM 32 بت و64 بت والمضمنة. إذا كانت هذه هي المرة الأولى التي تحاول فيها تحليل التعليمات البرمجية الثابتة للتحقق من مشاريعك، فنوصيك بالتعرف عليه مقالة - سلعة حول كيفية عرض تحذيرات PVS-Studio الأكثر إثارة للاهتمام بسرعة وتقييم إمكانيات هذه الأداة.

أزور ديف أوبس - مجموعة من الخدمات السحابية التي تغطي بشكل مشترك عملية التطوير بأكملها. تتضمن هذه المنصة أدوات مثل Azure Pipelines، وAzure Boards، وAzure Artifacts، وAzure Repos، وAzure Test Plans، والتي تتيح لك تسريع عملية إنشاء البرامج وتحسين جودتها.

تشوكولاتيي هو مدير حزم مفتوح المصدر لنظام التشغيل Windows. الهدف من المشروع هو أتمتة دورة حياة البرنامج بالكامل بدءًا من التثبيت وحتى التحديث وإلغاء التثبيت على أنظمة تشغيل Windows.

حول استخدام الشوكولاتة

يمكنك معرفة كيفية تثبيت مدير الحزم نفسه على هذا صلة. الوثائق الكاملة لتثبيت المحلل متاحة على صلة راجع التثبيت باستخدام قسم مدير الحزم Chocolatey. وسأكرر بإيجاز بعض النقاط من هناك.

أمر لتثبيت أحدث إصدار من المحلل:

choco install pvs-studio

أمر لتثبيت إصدار محدد من حزمة PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

افتراضيًا، يتم تثبيت قلب المحلل فقط، وهو المكون الأساسي. يمكن تمرير جميع العلامات الأخرى (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'

دعنا ننتقل إلى نص ملف التكوين (block سلم). على الرغم من أنه لا يمكنك تثبيت برنامج عشوائي على جهاز افتراضي، إلا أنني لم أقم بإضافة حاوية 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

هنا علينا أن نختار تثبيت في الميدان مع الفرق . في اسم الملف Nuspec قم بالإشارة إلى اسم الحزمة المطلوبة – pvs-studio. إذا لم تحدد الإصدار، فسيتم تثبيت الإصدار الأحدث الذي يناسبنا تمامًا. دعونا نضغط على الزر تضيف وسنرى المهمة التي تم إنشاؤها في ملف التكوين.

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

بعد ذلك، دعنا ننتقل إلى الجزء الرئيسي من ملفنا:

- task: CmdLine@2
  inputs:
    script: 

نحن الآن بحاجة إلى إنشاء ملف بترخيص المحلل. هنا PVSNAME и بفسكي – أسماء المتغيرات التي نحدد قيمها في الإعدادات. سيقومون بتخزين تسجيل الدخول ومفتاح الترخيص لـ PVS-Studio. لتعيين قيمها، افتح القائمة المتغيرات->متغير جديد. لنقم بإنشاء المتغيرات PVSNAME لتسجيل الدخول و بفسكي لمفتاح المحلل. لا تنس تحديد المربع حافظ على سرية هذه القيمة إلى بفسكي. رمز الأمر:

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

لنقم ببناء المشروع باستخدام ملف الخفافيش الموجود في المستودع:

с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#. دعونا نلقي نظرة على بعض الأخطاء التي تم العثور عليها.

نتائج الإختبار

تحذير رقم 1

تحذير المحلل: V3005 يتم تعيين متغير "الموفر" لنفسه. كريتبوهاشبروفيديرسبيكس.cs 38

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

اكتشف المحلل تخصيص المتغير لنفسه، وهو أمر غير منطقي. على الأرجح، بدلا من أحد هذه المتغيرات يجب أن يكون هناك متغير آخر. حسنا، أو هذا خطأ مطبعي، ويمكن ببساطة إزالة المهمة الإضافية.

تحذير رقم 2

تحذير المحلل: V3093 [CWE-480] يقوم عامل التشغيل '&' بتقييم كلا المعاملين. ربما يجب استخدام مشغل الدائرة القصيرة "&&" بدلاً من ذلك. منصة.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 أبدًا، وهو ما قد لا يكون بالضبط منطق العملية الذي توقعه المبرمج.

تحذير رقم 5

تحذير المحلل: V3123 [CWE-783] ربما يعمل عامل التشغيل '?:' بطريقة مختلفة عما كان متوقعًا. أولويتها أقل من أولوية المشغلين الآخرين في حالتها. خيارات.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 إذا تمت تهيئة بضعة أسطر أعلاه إلى الصفر، فسيقوم المشغل الثلاثي بإرجاع القيمة زائف. وبسبب هذا الشرط، سيتم تنفيذ جسم الحلقة مرة واحدة فقط. يبدو لي أن هذا الجزء من الكود لا يعمل على الإطلاق كما أراد المبرمج.

تحذير رقم 6

تحذير المحلل: V3022 [CWE-571] يكون التعبير 'installedPackageVersions.Count != 1' صحيحًا دائمًا. نوجيتسيرفيس.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والتي سوف تكون دائما صحيح. في كثير من الأحيان، يشير هذا التحذير إلى وجود خطأ منطقي في التعليمات البرمجية، وفي حالات أخرى يشير ببساطة إلى التحقق الزائد.

تحذير رقم 7

تحذير المحلل: V3001 توجد تعبيرات فرعية متطابقة 'commandArguments.contains("-apikey")' على يسار وعلى يمين '||' المشغل أو العامل. وسيطات Utility.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 من تطبيق المعلمة مفتاح API بضع طرق أخرى. كما هو الحال مع المعلمات أعلاه، يمكنني تقديم الخيارات التالية:

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

أخطاء النسخ واللصق لديها فرصة كبيرة للظهور عاجلاً أم آجلاً في أي مشروع يحتوي على كمية كبيرة من التعليمات البرمجية المصدر، وأحد أفضل الأدوات لمكافحتها هو التحليل الثابت.

ملاحظة: وكما هو الحال دائمًا، يميل هذا الخطأ إلى الظهور في نهاية الشرط متعدد الأسطر :). انظر المنشور"تأثير السطر الأخير".

تحذير رقم 8

تحذير المحلل: V3095 [CWE-476] تم استخدام كائن 'installedPackage' قبل التحقق من قيمته الخالية. تحقق من الأسطر: 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)
  {
    ....
  }
  ....
}

الخطأ الكلاسيكي: الكائن أولاً installpackage يتم استخدامه ومن ثم التحقق منه فارغة. يخبرنا هذا التشخيص عن إحدى مشكلتين في البرنامج: إما installpackage لا يساوي أبدا فارغة، وهو أمر مشكوك فيه، ومن ثم يصبح الشيك زائدًا عن الحاجة، أو من المحتمل أن نحصل على خطأ فادح في الكود - محاولة للوصول إلى مرجع فارغ.

اختتام

لذلك اتخذنا خطوة صغيرة أخرى - أصبح الآن استخدام 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

إضافة تعليق