From 69e9aada412e81575a95d0d94f4592fe1b8dfc15 Mon Sep 17 00:00:00 2001 From: Quanlong Huang Date: Fri, 24 Jul 2026 19:59:48 +0800 Subject: [PATCH 1/7] Fix std::max_align_t compilation error std::max_align_t is defined in header which is pulled in transitively via / on some libstdc++ versions, but that's not guaranteed. On GCC 11 that transitive include doesn't happen, so std::max_align_t is unresolved. This commit explicitly includes to resolve the issue. Bug: 538420330 Change-Id: I02805d316be9606e28d77ba592ac26865797c552 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8140782 Reviewed-by: Mike Frysinger Reviewed-by: Lei Zhang --- src/common/memory_allocator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/memory_allocator.h b/src/common/memory_allocator.h index c919a681..33f836b5 100644 --- a/src/common/memory_allocator.h +++ b/src/common/memory_allocator.h @@ -36,6 +36,7 @@ #include #include +#include #include #include From 418aacd617897c19d960ec3e649f42ea95a6363a Mon Sep 17 00:00:00 2001 From: Dominique Clause Date: Mon, 10 Aug 2026 08:29:49 +0000 Subject: [PATCH 2/7] Fix misaligned pointer use in SimpleSerializer::Write In SimpleSerializer::Write, placement new was used to construct objects at the destination memory address. When serializing data into unaligned byte buffers, dest is not guaranteed to satisfy alignof(Type), causing undefined behavior and runtime errors under AddressSanitizer or UndefinedBehaviorSanitizer (e.g. misaligned_pointer_use on unsigned long). Replace placement new with memcpy so that bytes are copied safely regardless of pointer alignment. Bug: 540850595 Change-Id: I7e0137ee92935665d7447a4490bbaaab462d0f58 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8231125 Reviewed-by: Joshua Peraza Reviewed-by: Ivan Penkov --- src/processor/simple_serializer.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/processor/simple_serializer.h b/src/processor/simple_serializer.h index bd6cc84c..3681fc70 100644 --- a/src/processor/simple_serializer.h +++ b/src/processor/simple_serializer.h @@ -38,6 +38,7 @@ #define PROCESSOR_SIMPLE_SERIALIZER_H__ #include +#include #include "google_breakpad/common/breakpad_types.h" @@ -54,8 +55,9 @@ template class SimpleSerializer { // Write 'item' to memory location 'dest', and return to the "end" address of // data written, i.e., the address after the final byte written. static char* Write(const Type& item, char* dest) { - new (dest) Type(item); - return dest + SizeOf(item); + const size_t size = SizeOf(item); + memcpy(dest, &item, size); + return dest + size; } }; From a9df3bd99cf8b863a92502ef906b5ddc399c2c9a Mon Sep 17 00:00:00 2001 From: XuJiaL1 <2922235917@qq.com> Date: Mon, 24 Aug 2026 19:33:13 +0800 Subject: [PATCH 3/7] Fix l_next and padding consistency in AugmentMappings Keep AlignUp for l_next (no over-padding when filename is 8-aligned) and derive padding from the same aligned size so they always match. Change-Id: Idb47659115bc168fd3728cd97573219f8f8f42b8 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8259656 Reviewed-by: Mike Frysinger Reviewed-by: Mark Mentovai --- src/tools/linux/md2core/minidump-2-core.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index be4be741..59ee589f 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -1287,16 +1287,18 @@ AugmentMappings(const Options& options, CrashedProcess* crashinfo, } } + const size_t aligned_filename_size = + PageAllocator::AlignUp(filename.size(), 8); if (std::distance(iter, crashinfo->link_map.end()) == 1) { link_map.l_next = 0; } else { link_map.l_next = (struct link_map*)(start_addr + data.size() + sizeof(link_map) + - PageAllocator::AlignUp(filename.size(), 8)); + aligned_filename_size); } data.append((char*)&link_map, sizeof(link_map)); data.append(filename); - data.append(8 - (filename.size() & 7), 0); + data.append(aligned_filename_size - filename.size(), 0); } AddDataToMapping(crashinfo, data, start_addr); From 9a2ad67542a4a40b0fdf558c0059a63d6cc5e359 Mon Sep 17 00:00:00 2001 From: Luis Sandoval Castro Date: Fri, 11 Sep 2026 15:52:39 -0700 Subject: [PATCH 4/7] Do not write a build id when identification fails HashElfTextSection is the fallback used when an ELF has no build id note: hash the first page of .text. It resized the output buffer before the check that can fail, so when .text could not be found either it returned false with 16 zero bytes left in the identifier buffer. The caller discards the return value and tests the buffer instead: dumper_->ElfFileIdentifierForMapping(mapping, member, mapping_id, identifier_bytes); ... if (!identifier_bytes.empty()) { wasteful_vector derives from std::vector, so resize value-initializes and the bytes are deterministically zero. A CV record was therefore written with an all-zero build id whenever identification failed. That is why the symptom read as a missing symbol upload rather than a broken dump: an all-zero build id looks like a build id nobody uploaded symbols for, while no build id at all points at the writer. Move the resize below the check so a failed identification leaves the buffer empty and no CV record is written. MicrodumpWriter indexed the identifier unconditionally, which is undefined on an empty vector even though the copy length would be zero. Guard it. Testing Built libbreakpad_client.a, core2md, dump_syms and minidump_stackwalk. The autotools suite passes on x86-64 Linux: 48 of 48 test programs. FailedIdentificationLeavesNoBytes in file_id_unittest.cc covers it: identification of a buffer with no build id note and no .text must return false and leave the identifier empty. It fails without this commit, with a 16-byte identifier of zeros. Change-Id: Ie2d787320c459b0dbfadab8828020f15574682d5 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8398976 Reviewed-by: Mark Mentovai Reviewed-by: Mike Frysinger --- .../linux/microdump_writer/microdump_writer.cc | 6 ++++-- src/common/linux/file_id.cc | 6 ++++-- src/common/linux/file_id_unittest.cc | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 27c245a7..34a6eb63 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -475,8 +475,10 @@ class MicrodumpWriter { // Copy as many bytes of |identifier| as will fit into a MDGUID MDGUID module_identifier = {0}; - memcpy(&module_identifier, &identifier_bytes[0], - std::min(sizeof(MDGUID), identifier_bytes.size())); + if (!identifier_bytes.empty()) { + memcpy(&module_identifier, &identifier_bytes[0], + std::min(sizeof(MDGUID), identifier_bytes.size())); + } char file_name[NAME_MAX]; char file_path[NAME_MAX]; diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index 8dc5a57f..14dc043c 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -127,8 +127,6 @@ static bool FindElfBuildIDNote(const void* elf_mapped_base, // a simple hash by XORing the first page worth of bytes into |identifier|. static bool HashElfTextSection(const void* elf_mapped_base, wasteful_vector& identifier) { - identifier.resize(kMDGUIDSize); - void* text_section; size_t text_size; if ((!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, @@ -136,11 +134,15 @@ static bool HashElfTextSection(const void* elf_mapped_base, !FindElfSection(elf_mapped_base, "text", SHT_PROGBITS, (const void**)&text_section, &text_size)) || text_size == 0) { + // Leave |identifier| untouched. A caller that sees bytes here would + // write them as a build id, turning "cannot identify this module" into + // a valid-looking all-zero one. return false; } // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this // function backwards-compatible. + identifier.resize(kMDGUIDSize); my_memset(&identifier[0], 0, kMDGUIDSize); const uint8_t* ptr = reinterpret_cast(text_section); const uint8_t* ptr_end = ptr + std::min(text_size, static_cast(4096)); diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc index 5b0c3fef..ad38146c 100644 --- a/src/common/linux/file_id_unittest.cc +++ b/src/common/linux/file_id_unittest.cc @@ -455,3 +455,19 @@ TYPED_TEST(FileIDTest, ConvertIdentifierToString) { ASSERT_EQ(kExpected, FileID::ConvertIdentifierToString(identifier)); } + +// A failed identification must leave the identifier EMPTY, so FillRawModule +// writes no CV record at all. Leaving bytes behind turns "cannot identify +// this module" into a valid-looking all-zero build id, which reads downstream +// as a missing symbol upload rather than a broken minidump. +TEST(FileIDTest, FailedIdentificationLeavesNoBytes) { + // Not an ELF: no build-id note to find, and no .text section to hash. + uint8_t not_an_elf[4096] = {}; + + PageAllocator allocator; + auto_wasteful_vector identifier(&allocator); + + EXPECT_FALSE( + FileID::ElfFileIdentifierFromMappedFile(not_an_elf, identifier)); + EXPECT_TRUE(identifier.empty()); +} From 868abe6f016cfeabfb7208681e89031ae667c336 Mon Sep 17 00:00:00 2001 From: Yue She Date: Thu, 17 Sep 2026 17:20:48 -0400 Subject: [PATCH 5/7] mac: Don't fail cache extraction on delta cryptex images upload system symbols is failing on the latest MacOS27 installer, while extracting dyld cache from `cryptex_cryptex-system-arm64e.x1` with the error `couldn't find System/Library/dyld`. `.x1` image is a delta image on top of a baseline image, so it seems like it does not contain dyld cache. Bug: 562142544 Change-Id: I1fa249832009c321a69d782411d1d877faaecf26 Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8415769 Reviewed-by: Mark Mentovai --- .../upload_system_symbols/archive/extract.go | 38 +++++++++- .../archive/extract_test.go | 73 +++++++++++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src/tools/mac/upload_system_symbols/archive/extract_test.go diff --git a/src/tools/mac/upload_system_symbols/archive/extract.go b/src/tools/mac/upload_system_symbols/archive/extract.go index 965e154e..f8568b3b 100644 --- a/src/tools/mac/upload_system_symbols/archive/extract.go +++ b/src/tools/mac/upload_system_symbols/archive/extract.go @@ -312,6 +312,10 @@ func (e *installAssistantExtractor) hasCryptexes(plistPath string) (bool, error) } } +// imagePatchManifestPath is where an installer's asset archive holds the manifest +// describing its image patches, keyed by each patch's file name. +const imagePatchManifestPath = "AssetData/image_patches.plist" + // extractCachesFromZips extracts zips that contain dyld shared caches, and extracts the dyld shared caches from them. // The specifics depend on whether this installer uses cryptexes or payload files. func (e *installAssistantExtractor) extractCachesFromZips(zips []string, destination string, hasCryptexes bool) error { @@ -324,10 +328,17 @@ func (e *installAssistantExtractor) extractCachesFromZips(zips []string, destina return fmt.Errorf("couldn't extract caches from %v: %v", containerPath, err) } } else { + // The manifest goes somewhere other than `containerPath`, which + // extractCachesFromCryptexes reads expecting nothing but image patches. + manifestDir := path.Join(e.scratchDir, "image_patch_manifest") + if err := e.unarchiveZipsMatching(zips, manifestDir, imagePatchManifestPath); err != nil { + return err + } if err := e.unarchiveZipsMatching(zips, containerPath, "AssetData/payloadv2/image_patches/cryptex-system-*"); err != nil { return err } - if err := e.extractCachesFromCryptexes(containerPath, destination); err != nil { + manifest := path.Join(manifestDir, path.Base(imagePatchManifestPath)) + if err := e.extractCachesFromCryptexes(containerPath, manifest, destination); err != nil { return fmt.Errorf("couldn't extract caches from %v: %v", containerPath, err) } } @@ -428,8 +439,9 @@ func (e *installAssistantExtractor) copySharedCaches(from, to string) error { } // extractCachesFromCryptexes extracts disk images from any cryptexes at `cryptexesPath`, mounts them, -// and extracts any dyld shared caches to `destination`. -func (e *installAssistantExtractor) extractCachesFromCryptexes(cryptexesPath string, destination string) error { +// and extracts any dyld shared caches to `destination`. `manifest` is the image patch manifest +// describing those cryptexes. +func (e *installAssistantExtractor) extractCachesFromCryptexes(cryptexesPath string, manifest string, destination string) error { scratchDir, err := os.MkdirTemp(e.scratchDir, "cryptex_dmg") if err != nil { return err @@ -446,12 +458,32 @@ func (e *installAssistantExtractor) extractCachesFromCryptexes(cryptexesPath str e.vlog("Mounting %s at %s\n", cryptex, dmgPath) e.mountDMG(dmgPath, cryptexMountpoint) if err := e.copySharedCaches(cryptexMountpoint, destination); err != nil { + // A delta image patches another image rather than containing one, so it + // can't necessarily be turned into a disk image to take caches from. For now, + // ignore the failure and proceed to the next image cache extraction. + if e.isDeltaImage(manifest, f.Name()) { + e.vlog("Ignoring %v: %v. It patches another image rather than replacing it.\n", + cryptex, err) + continue + } return err } } return nil } +// isDeltaImage returns true if the image contains "ImagePatchBaselineTag" in the plist file, +// indicating that the image is a delta one, built on top of a baseline image. +func (e *installAssistantExtractor) isDeltaImage(manifestPath string, imageName string) bool { + print_cmd := fmt.Sprintf("print :%s:ImagePatchBaselineTag", imageName) + baseline, err := exec.Command("/usr/libexec/PlistBuddy", "-c", print_cmd, manifestPath).Output() + if err != nil { + return false + } + e.vlog("%v patches %v\n", imageName, strings.TrimSpace(string(baseline))) + return true +} + // extractCryptexDMG extracts the cryptex at `cryptexPath` to `dmgPath` using libParallelCompression. func (e *installAssistantExtractor) extractCryptexDMG(cryptexPath, dmgPath string) error { inp := C.CString("") diff --git a/src/tools/mac/upload_system_symbols/archive/extract_test.go b/src/tools/mac/upload_system_symbols/archive/extract_test.go new file mode 100644 index 00000000..1409f10f --- /dev/null +++ b/src/tools/mac/upload_system_symbols/archive/extract_test.go @@ -0,0 +1,73 @@ +package archive + +import ( + "os" + "path" + "testing" +) + +// imagePatchManifest is the image patch manifest from a macOS 27 installer, whose +// cryptex-system-arm64e.x1 image patches cryptex-system-arm64e rather than containing an +// image of its own. +const imagePatchManifest = ` + + + + cryptex-app + + ImagePatchTag + cryptex-app + + cryptex-system-arm64e + + ImagePatchTag + cryptex-system-arm64e + + cryptex-system-arm64e.x1 + + ImagePatchBaselineTag + cryptex-system-arm64e + ImagePatchTag + cryptex-system-arm64e.x1 + + cryptex-system-rosetta + + ImagePatchTag + cryptex-system-rosetta + + + +` + +func TestIsDeltaImage(t *testing.T) { + dir := t.TempDir() + manifestPath := path.Join(dir, "image_patches.plist") + if err := os.WriteFile(manifestPath, []byte(imagePatchManifest), 0644); err != nil { + t.Fatalf("couldn't write %s: %v", manifestPath, err) + } + e := &installAssistantExtractor{Extractor: &Extractor{}} + + cases := []struct { + imageName string + want bool + }{ + {"cryptex-system-arm64e", false}, + {"cryptex-system-arm64e.x1", true}, + {"cryptex-system-rosetta", false}, + {"cryptex-app", false}, + {"not-in-the-manifest", false}, + } + for _, c := range cases { + t.Run(c.imageName, func(t *testing.T) { + if got := e.isDeltaImage(manifestPath, c.imageName); got != c.want { + t.Errorf("isDeltaImage(%s) = %v, want %v", c.imageName, got, c.want) + } + }) + } + + t.Run("no manifest", func(t *testing.T) { + if e.isDeltaImage(path.Join(dir, "does_not_exist.plist"), "cryptex-system-arm64e.x1") { + t.Error("isDeltaImage with no manifest = true, want false") + } + }) +} From 6598c9c33fc02da7805401f3b0f1a733e6a24071 Mon Sep 17 00:00:00 2001 From: Evan Brown Date: Fri, 25 Sep 2026 19:42:40 +0000 Subject: [PATCH 6/7] Relax page count check in WastefulVectorTest.Simple WastefulVectorTest.Simple pushes 256 elements into a wasteful_vector backed by a PageAllocator and previously asserted that exactly 1 page (4096 bytes) was allocated. Because PageAllocator does not free old allocations when std::vector reallocates, the total memory allocated depends on the std::vector implementation's growth factor and capacity decisions (for example, when using a lower growth factor or size-returning allocation). Track the total bytes used across capacity increases and verify that allocator_.pages_allocated() is at most total_used / 4096 + 1. Also include for size_t. Change-Id: I0642a3edd2747a72fae1fff61b9191b0945c650f Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/8465926 Reviewed-by: Primiano Tucci Reviewed-by: Ivan Penkov --- src/common/memory_allocator_unittest.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/common/memory_allocator_unittest.cc b/src/common/memory_allocator_unittest.cc index 08e0f8b8..1bdb8d7f 100644 --- a/src/common/memory_allocator_unittest.cc +++ b/src/common/memory_allocator_unittest.cc @@ -32,6 +32,7 @@ #include +#include #include #include "breakpad_googletest_includes.h" @@ -135,14 +136,21 @@ TEST(WastefulVectorTest, Simple) { EXPECT_EQ(0U, allocator_.pages_allocated()); wasteful_vector v(&allocator_); + size_t total_used = 0; for (unsigned i = 0; i < 256; ++i) { + const size_t prev_capacity = v.capacity(); v.push_back(i); + const size_t new_capacity = v.capacity(); + if (new_capacity > prev_capacity) { + total_used += new_capacity * sizeof(unsigned); + } ASSERT_EQ(i, v.back()); ASSERT_EQ(&v.back(), &v[i]); } ASSERT_FALSE(v.empty()); ASSERT_EQ(v.size(), 256u); - EXPECT_EQ(1U, allocator_.pages_allocated()); + EXPECT_LE(allocator_.pages_allocated(), + total_used / 4096 + 1); for (unsigned i = 0; i < 256; ++i) ASSERT_EQ(v[i], i); } From 409cdcac688576723f80478d07669261664938d6 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Thu, 8 Oct 2026 02:18:36 +0200 Subject: [PATCH 7/7] CI: delete upstream GitHub actions, do not close pull requests We definitely don't want the close-pull-request action. The build-test-ci and coverity workflows make heavy usage of gclient, we may not do that. If we want a CI, we will do it ourselves our own way. --- .github/workflows/build-test-ci.yml | 73 ------------------------ .github/workflows/close-pull-request.yml | 22 ------- .github/workflows/coverity.yml | 43 -------------- 3 files changed, 138 deletions(-) delete mode 100644 .github/workflows/build-test-ci.yml delete mode 100644 .github/workflows/close-pull-request.yml delete mode 100644 .github/workflows/coverity.yml diff --git a/.github/workflows/build-test-ci.yml b/.github/workflows/build-test-ci.yml deleted file mode 100644 index 2196d55f..00000000 --- a/.github/workflows/build-test-ci.yml +++ /dev/null @@ -1,73 +0,0 @@ -# GitHub actions workflow. -# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions - -name: Build+Test CI - -on: - push: - branches: [main] - - schedule: - # The GH mirroring from Google GoB does not trigger push actions. - # Fire it every other day to provide some coverage. This will run ~8 AM PT. - - cron: '39 3 */2 * *' - - # Allow for manual triggers from the web. - workflow_dispatch: - -jobs: - autotools: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - cc: gcc - cxx: g++ - - os: ubuntu-latest - cc: clang - cxx: clang++ - - os: macos-latest - cc: clang - cxx: clang++ - runs-on: ${{ matrix.os }} - env: - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - steps: - - name: System settings - run: | - set -x - $CC --version - $CXX --version - getconf _NPROCESSORS_ONLN - getconf _NPROCESSORS_CONF - true - - - name: Checkout depot_tools - run: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git ../depot_tools - - - name: Checkout breakpad - run: | - set -xe - PATH+=:$PWD/../depot_tools - gclient config --unmanaged --name=src https://github.com/${{ github.repository }} - gclient sync --no-history --nohooks - - # First build & test in-tree. - - run: ./configure --disable-silent-rules - working-directory: src - - run: make -j$(getconf _NPROCESSORS_CONF) - working-directory: src - - run: make -j$(getconf _NPROCESSORS_CONF) check VERBOSE=1 - working-directory: src - - run: make -j$(getconf _NPROCESSORS_CONF) distclean - working-directory: src - - # Then build & test out-of-tree. - - run: mkdir -p src/build/native - - run: ../../configure --disable-silent-rules - working-directory: src/build/native - - run: make -j$(getconf _NPROCESSORS_CONF) distcheck VERBOSE=1 - working-directory: src/build/native diff --git a/.github/workflows/close-pull-request.yml b/.github/workflows/close-pull-request.yml deleted file mode 100644 index da11c4a6..00000000 --- a/.github/workflows/close-pull-request.yml +++ /dev/null @@ -1,22 +0,0 @@ -# GitHub actions workflow. -# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions - -# https://github.com/superbrothers/close-pull-request -name: Close Pull Request - -on: - pull_request_target: - types: [opened] - -jobs: - run: - runs-on: ubuntu-latest - steps: - - uses: superbrothers/close-pull-request@v3 - with: - comment: > - Thanks for your contribution! - Unfortunately, we don't use GitHub pull requests to manage code - contributions to this repository. - Instead, please see [README.md](../blob/HEAD/README.md) which - provides full instructions on how to get involved. diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml deleted file mode 100644 index 06f8e276..00000000 --- a/.github/workflows/coverity.yml +++ /dev/null @@ -1,43 +0,0 @@ -# GitHub actions workflow. -# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions - -# https://scan.coverity.com/projects/google-breakpad -name: Coverity Scan - -on: - push: - branches: [main] - - schedule: - # The GH mirroring from Google GoB does not trigger push actions. - # Fire it once a week to provide some coverage. - - cron: '39 2 * * WED' - - # Allow for manual triggers from the web. - workflow_dispatch: - -jobs: - coverity: - runs-on: ubuntu-latest - env: - CC: clang - CXX: clang++ - steps: - - name: Checkout depot_tools - run: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git ../depot_tools - - - name: Checkout breakpad - run: | - set -xe - PATH+=:$PWD/../depot_tools - gclient config --unmanaged --name=src https://github.com/${{ github.repository }} - gclient sync --no-history --nohooks - - - run: ./configure --disable-silent-rules - working-directory: src - - - uses: vapier/coverity-scan-action@v1 - with: - command: make -C src -O -j$(getconf _NPROCESSORS_CONF) - email: ${{ secrets.COVERITY_SCAN_EMAIL }} - token: ${{ secrets.COVERITY_SCAN_TOKEN }}