PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps
Chúng tôi tiếp tục làm cho việc sử dụng PVS-Studio trở nên thuận tiện hơn. Máy phân tích của chúng tôi hiện có sẵn trong Chocolatey, một trình quản lý gói dành cho Windows. Chúng tôi tin rằng điều này sẽ tạo điều kiện thuận lợi cho việc triển khai PVS-Studio, đặc biệt là trong các dịch vụ đám mây. Để không đi xa, chúng ta hãy kiểm tra mã nguồn của cùng một loại Chocolatey. Azure DevOps sẽ hoạt động như một hệ thống CI.

Dưới đây là danh sách các bài viết khác của chúng tôi về chủ đề tích hợp với hệ thống đám mây:

Tôi khuyên bạn nên chú ý đến bài viết đầu tiên về tích hợp với Azure DevOps, vì trong trường hợp này một số điểm được lược bỏ để không bị trùng lặp.

Vì vậy, những anh hùng của bài viết này:

PVS Studio là một công cụ phân tích mã tĩnh được thiết kế để xác định lỗi và lỗ hổng tiềm ẩn trong các chương trình được viết bằng C, C++, C# và Java. Chạy trên các hệ thống Windows, Linux và macOS 64 bit và có thể phân tích mã được thiết kế cho nền tảng ARM 32 bit, 64 bit và nhúng. Nếu đây là lần đầu tiên bạn thử phân tích mã tĩnh để kiểm tra dự án của mình, chúng tôi khuyên bạn nên tự làm quen với bài báo về cách xem nhanh các cảnh báo PVS-Studio thú vị nhất và đánh giá khả năng của công cụ này.

Azure DevOps — một tập hợp các dịch vụ đám mây cùng bao trùm toàn bộ quá trình phát triển. Nền tảng này bao gồm các công cụ như Azure Pipelines, Azure Boards, Azure Artifacts, Azure Repos, Azure Test Plans, cho phép bạn tăng tốc quá trình tạo phần mềm và cải thiện chất lượng của phần mềm.

Sô cô la là một trình quản lý gói nguồn mở cho Windows. Mục tiêu của dự án là tự động hóa toàn bộ vòng đời phần mềm từ cài đặt đến cập nhật và gỡ cài đặt trên hệ điều hành Windows.

Về việc sử dụng Chocolatey

Bạn có thể xem cách cài đặt trình quản lý gói tại đây liên kết. Tài liệu đầy đủ để cài đặt máy phân tích có sẵn tại liên kết Xem phần Cài đặt bằng trình quản lý gói Chocolatey. Tôi sẽ nhắc lại ngắn gọn một số điểm từ đó.

Lệnh cài đặt phiên bản mới nhất của máy phân tích:

choco install pvs-studio

Lệnh cài đặt phiên bản cụ thể của gói PVS-Studio:

choco install pvs-studio --version=7.05.35617.2075

Theo mặc định, chỉ có lõi của máy phân tích, thành phần Core, được cài đặt. Tất cả các cờ khác (Standone, JavaCore, IDEA, MSVS2010, MSVS2012, MSVS2013, MSVS2015, MSVS2017, MSVS2019) có thể được chuyển bằng --package-parameters.

Ví dụ về lệnh sẽ cài đặt trình phân tích có plugin cho Visual Studio 2019:

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

Bây giờ hãy xem một ví dụ về cách sử dụng thuận tiện bộ phân tích trong Azure DevOps.

điều chỉnh

Hãy để tôi nhắc bạn rằng có một phần riêng về các vấn đề như đăng ký tài khoản, tạo Đường dẫn xây dựng và đồng bộ hóa tài khoản của bạn với một dự án nằm trong kho GitHub. bài viết. Quá trình thiết lập của chúng tôi sẽ ngay lập tức bắt đầu bằng việc viết tệp cấu hình.

Trước tiên, hãy thiết lập trình kích hoạt khởi chạy, cho biết rằng chúng tôi chỉ khởi chạy khi có những thay đổi trong chủ chi nhánh:

trigger:
- master

Tiếp theo chúng ta cần chọn một máy ảo. Hiện tại, nó sẽ là một tác nhân do Microsoft lưu trữ với Windows Server 2019 và Visual Studio 2019:

pool:
  vmImage: 'windows-latest'

Hãy chuyển sang phần nội dung của tệp cấu hình (khối bước). Mặc dù thực tế là bạn không thể cài đặt phần mềm tùy ý vào máy ảo nhưng tôi đã không thêm vùng chứa Docker. Chúng tôi có thể thêm Chocolatey làm tiện ích mở rộng cho Azure DevOps. Để làm điều này, chúng ta hãy đi đến liên kết. Nhấp chuột Miễn phí. Tiếp theo, nếu bạn đã được ủy quyền, chỉ cần chọn tài khoản của bạn, nếu không, hãy làm điều tương tự sau khi được ủy quyền.

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Tại đây bạn cần chọn nơi chúng tôi sẽ thêm tiện ích mở rộng và nhấp vào nút đặt.

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Sau khi cài đặt thành công nhấn Tiến tới tổ chức:

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Bây giờ bạn có thể xem mẫu cho tác vụ Chocolatey trong cửa sổ nhiệm vụ khi chỉnh sửa tập tin cấu hình azure-pipelines.yml:

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Nhấp vào Chocolatey và xem danh sách các trường:

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Ở đây chúng ta cần chọn cài đặt, dựng lên trên sân cùng các đội. TRONG Tên tệp Nuspec cho biết tên của gói được yêu cầu – pvs-studio. Nếu bạn không chỉ định phiên bản, phiên bản mới nhất sẽ được cài đặt, phiên bản này hoàn toàn phù hợp với chúng tôi. Hãy nhấn nút thêm vào và chúng ta sẽ thấy tác vụ được tạo trong tệp cấu hình.

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

Tiếp theo, hãy chuyển sang phần chính của tệp của chúng tôi:

- task: CmdLine@2
  inputs:
    script: 

Bây giờ chúng ta cần tạo một tệp có giấy phép phân tích. Đây PVSNAME и PVSKEY – tên của các biến có giá trị chúng tôi chỉ định trong cài đặt. Họ sẽ lưu trữ mã cấp phép và đăng nhập PVS-Studio. Để đặt giá trị của chúng, hãy mở menu Biến->Biến mới. Hãy tạo các biến PVSNAME để đăng nhập và PVSKEY cho phím phân tích. Đừng quên đánh dấu vào ô Giữ bí mật giá trị này cho PVSKEY. Mã lệnh:

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

Hãy xây dựng dự án bằng tệp bat nằm trong kho lưu trữ:

сall build.bat

Hãy tạo một thư mục nơi các tệp có kết quả của máy phân tích sẽ được lưu trữ:

сall mkdir PVSTestResults

Hãy bắt đầu phân tích dự án:

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

Chúng tôi chuyển đổi báo cáo của mình sang định dạng html bằng tiện ích PlogСonverter:

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

Bây giờ bạn cần tạo một tác vụ để có thể tải báo cáo lên.

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

Tệp cấu hình hoàn chỉnh trông như thế này:

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

Hãy nhấp vào Lưu-> Lưu-> Chạy để chạy nhiệm vụ. Hãy tải xuống báo cáo bằng cách chuyển đến tab nhiệm vụ.

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Dự án Chocolatey chỉ chứa 37615 dòng mã C#. Hãy xem xét một số lỗi được tìm thấy.

Kết quả kiểm tra

Cảnh báo N1

Cảnh báo máy phân tích: V3005 Biến 'Nhà cung cấp' được gán cho chính nó. CrytpoHashProviderSpecs.cs 38

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

Máy phân tích đã phát hiện việc gán biến cho chính nó, điều này không có ý nghĩa gì. Rất có thể, thay vì một trong những biến này sẽ có một biến khác. Chà, hoặc đây là một lỗi đánh máy và bài tập bổ sung có thể được loại bỏ một cách đơn giản.

Cảnh báo N2

Cảnh báo máy phân tích: V3093 [CWE-480] Toán tử '&' đánh giá cả hai toán hạng. Có lẽ nên sử dụng toán tử '&&' ngắn mạch để thay thế. Nền tảng.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;
  }
}

Sự khác biệt của nhà điều hành & từ nhà điều hành && đó là nếu phía bên trái của biểu thức là sai, thì vế phải vẫn sẽ được tính, trong trường hợp này hàm ý các lệnh gọi phương thức không cần thiết system.directory_exists.

Trong đoạn được xem xét, đây là một sai sót nhỏ. Có, điều kiện này có thể được tối ưu hóa bằng cách thay thế toán tử & bằng toán tử &&, nhưng từ quan điểm thực tế, điều này không ảnh hưởng gì cả. Tuy nhiên, trong các trường hợp khác, sự nhầm lẫn giữa & và && có thể gây ra vấn đề nghiêm trọng khi phía bên phải của biểu thức được xử lý bằng các giá trị không chính xác/không hợp lệ. Ví dụ: trong bộ sưu tập lỗi của chúng tôi, được xác định bằng chẩn đoán V3093, có trường hợp này:

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

Ngay cả khi chỉ số k không chính xác, nó sẽ được sử dụng để truy cập một phần tử mảng. Kết quả là một ngoại lệ sẽ được đưa ra IndexOutOfRangeNgoại lệ.

Cảnh báo N3, N4

Cảnh báo máy phân tích: V3022 [CWE-571] Biểu thức 'shortPrompt' luôn đúng. InteractivePrompt.cs 101
Cảnh báo máy phân tích: V3022 [CWE-571] Biểu thức 'shortPrompt' luôn đúng. 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
    ....
  }
  ....
}

Trong trường hợp này, có một logic kỳ lạ đằng sau hoạt động của toán tử bậc ba. Chúng ta hãy xem xét kỹ hơn: nếu điều kiện tôi đánh dấu bằng số 1 được đáp ứng thì chúng ta sẽ chuyển sang điều kiện 2, luôn luôn là đúng, nghĩa là dòng 3 sẽ được thực thi. Nếu điều kiện 1 sai thì chúng ta sẽ chuyển đến dòng được đánh số 4, điều kiện trong đó cũng luôn đúng đúng, có nghĩa là dòng 5 sẽ được thực thi. Do đó, các điều kiện được đánh dấu bằng chú thích 0 sẽ không bao giờ được đáp ứng, điều này có thể không chính xác theo logic hoạt động mà người lập trình mong đợi.

Cảnh báo N5

Cảnh báo máy phân tích: V3123 [CWE-783] Có lẽ toán tử '?:' hoạt động theo cách khác với mong đợi. Mức độ ưu tiên của nó thấp hơn mức độ ưu tiên của các toán tử khác trong tình trạng của nó. Tùy chọn.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);
  }
}

Chẩn đoán đã hoạt động cho dòng:

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

Vì biến j một vài dòng trên được khởi tạo về XNUMX, toán tử bậc ba sẽ trả về giá trị sai. Vì điều kiện này nên phần thân của vòng lặp sẽ chỉ được thực hiện một lần. Đối với tôi, có vẻ như đoạn mã này hoàn toàn không hoạt động như dự định của người lập trình.

Cảnh báo N6

Cảnh báo máy phân tích: V3022 [CWE-571] Biểu thức 'installedPackageVersions.Count != 1' luôn đúng. 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);
    }
    ....
  }
  ....
}

Có một điều kiện lồng nhau kỳ lạ ở đây: đã cài đặtPackageVersions.Count != 1điều đó sẽ luôn như vậy đúng. Thông thường, cảnh báo như vậy chỉ ra lỗi logic trong mã và trong các trường hợp khác, nó chỉ đơn giản biểu thị việc kiểm tra dư thừa.

Cảnh báo N7

Cảnh báo máy phân tích: V3001 Có các biểu thức con giống hệt nhau 'commandArguments.contains("-apikey")' ở bên trái và bên phải của '||' nhà điều hành. 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");
}

Lập trình viên viết phần mã này đã sao chép và dán hai dòng cuối cùng và quên chỉnh sửa chúng. Vì điều này, người dùng Chocolatey không thể áp dụng tham số Mã API một vài cách nữa. Tương tự như các thông số trên, tôi có thể đưa ra các tùy chọn sau:

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

Lỗi sao chép-dán có khả năng xuất hiện sớm hay muộn trong bất kỳ dự án nào có số lượng mã nguồn lớn và một trong những công cụ tốt nhất để chống lại chúng là phân tích tĩnh.

Tái bút Và như mọi khi, lỗi này có xu hướng xuất hiện ở cuối điều kiện nhiều dòng :). Xem ấn phẩm "Hiệu ứng dòng cuối cùng".

Cảnh báo N8

Cảnh báo máy phân tích: V3095 [CWE-476] Đối tượng 'installedPackage' đã được sử dụng trước khi nó được xác minh là rỗng. Kiểm tra các dòng: 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)
  {
    ....
  }
  ....
}

Sai lầm kinh điển: đối tượng đầu tiên đã cài đặtGói được sử dụng và sau đó được kiểm tra vô giá trị. Chẩn đoán này cho chúng ta biết về một trong hai vấn đề trong chương trình: đã cài đặtGói không bao giờ bằng vô giá trị, điều này đáng nghi ngờ và khi đó việc kiểm tra là dư thừa hoặc chúng tôi có thể gặp lỗi nghiêm trọng trong mã - một nỗ lực truy cập vào một tham chiếu null.

Kết luận

Vậy là chúng ta đã thực hiện được một bước nhỏ nữa - giờ đây việc sử dụng PVS-Studio thậm chí còn trở nên dễ dàng và thuận tiện hơn. Tôi cũng muốn nói rằng Chocolatey là một trình quản lý gói tốt với một số lỗi nhỏ trong mã, thậm chí có thể ít hơn khi sử dụng PVS-Studio.

Chúng tôi mời bạn tải về và thử PVS-Studio. Việc sử dụng thường xuyên máy phân tích tĩnh sẽ cải thiện chất lượng và độ tin cậy của mã mà nhóm của bạn phát triển và giúp ngăn ngừa nhiều lỗi. lỗ hổng zero day.

PS

Trước khi xuất bản, chúng tôi đã gửi bài báo cho các nhà phát triển Chocolatey và họ đã đón nhận nó rất nồng nhiệt. Chúng tôi không tìm thấy bất kỳ điều gì nghiêm trọng, nhưng chẳng hạn, họ thích lỗi mà chúng tôi phát hiện có liên quan đến khóa “api-key”.

PVS-Studio hiện có trong Chocolatey: kiểm tra Chocolatey từ Azure DevOps

Nếu bạn muốn chia sẻ bài viết này với khán giả nói tiếng Anh, vui lòng sử dụng liên kết dịch: Vladislav Stolyarov. PVS-Studio hiện có phiên bản Chocolatey: Kiểm tra Chocolatey trong Azure DevOps.

Nguồn: www.habr.com

Thêm một lời nhận xét