Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
935af58
feat(sarif): add --base-dir support for relative SARIF artifact URIs
SizzleUnrlsd Feb 13, 2026
4eba918
docs(ci): document CI integration and add GitHub Actions consumer exa…
SizzleUnrlsd Feb 13, 2026
6ec80b5
docs(ci): document CI integration and add GitHub Actions consumer exa…
SizzleUnrlsd Feb 13, 2026
d8ca2fd
test(ci): add CI integration workflow for GitHub Action and Docker paths
SizzleUnrlsd Feb 13, 2026
b46be1e
feat(action): add composite GitHub Action and Docker packaging for an…
SizzleUnrlsd Feb 13, 2026
a210023
ci(workflows): add self-analysis and SARIF upload to main CI workflow
SizzleUnrlsd Feb 13, 2026
5a63ec1
feat(ci): add reusable CI analysis adapter script with compdb discove…
SizzleUnrlsd Feb 13, 2026
604ee15
refactor(analysis): simplify mem intrinsic kind classification with s…
SizzleUnrlsd Feb 13, 2026
5e1f567
test(cpy-buffer): add coverage for name-based mem intrinsics and non-…
SizzleUnrlsd Feb 13, 2026
40be2a9
test(escape-stack): add regression for lambda by-reference capture cl…
SizzleUnrlsd Feb 13, 2026
a48889d
fix(analysis): avoid false stack-pointer-escape diagnostics for lambd…
SizzleUnrlsd Feb 13, 2026
6a68469
fix(analysis): compare normalized short-circuit condition signatures …
SizzleUnrlsd Feb 13, 2026
170f405
test(diagnostics): add regressions for short-circuit and threshold-vs…
SizzleUnrlsd Feb 13, 2026
be8fbcb
chore(main): remove duplicated code
SizzleUnrlsd Feb 13, 2026
bc3db5e
ci(workflows): trigger build workflow on all branches for push and pu…
SizzleUnrlsd Feb 22, 2026
c4ba259
ci(integration): pull runtime image from GHCR instead of building loc…
SizzleUnrlsd Feb 22, 2026
a88ef04
ci(registry): add GHCR publish workflow for runtime and CI images
SizzleUnrlsd Feb 22, 2026
28e6455
docs(ci): document reusable action module and docker consumer workflows
SizzleUnrlsd Feb 22, 2026
077caa5
feat(action): improve composite action defaults with compdb autodisco…
SizzleUnrlsd Feb 22, 2026
a018875
refactor(docker): factorize CI image on top of runtime image
SizzleUnrlsd Feb 22, 2026
4291736
feat(docker): package analyzer runtime with CI tooling and models
SizzleUnrlsd Feb 22, 2026
cc984d1
fix(docker): harden entrypoint defaults and compatibility symlink gua…
SizzleUnrlsd Feb 22, 2026
ff6e7c4
feat(resource-lifetime): add model-driven ownership analysis and cros…
SizzleUnrlsd Feb 22, 2026
eac8886
feat(uninitialized): improve cross-tu and external out-param initiali…
SizzleUnrlsd Feb 22, 2026
2289afb
fix(compdb): preserve compile command identity and skip unsupported i…
SizzleUnrlsd Feb 22, 2026
17cac61
feat(stack-escape): externalize noescape modeling and split resolver …
SizzleUnrlsd Feb 22, 2026
7174db8
refactor(analysis): improve helper utilities and diagnostics plumbing
SizzleUnrlsd Feb 22, 2026
1ae345d
test(harness): extend regression runner for docker and model-based ch…
SizzleUnrlsd Feb 22, 2026
c0dab57
test(diagnostics): add duplicate-else-if edge-case coverage
SizzleUnrlsd Feb 22, 2026
0bebf0d
test(recursion): extend recursion detection and progression scenarios
SizzleUnrlsd Feb 22, 2026
40c070a
test(uninitialized): add out-param and cross-tu initialization regres…
SizzleUnrlsd Feb 22, 2026
ab9b9ca
test(vla): add read-side VLA regression coverage
SizzleUnrlsd Feb 22, 2026
c910e92
test(stack-escape): add noescape and callback escape regression cases
SizzleUnrlsd Feb 22, 2026
b4220cf
test(false-positives): add repro corpus for vulkan/stb/resource diagn…
SizzleUnrlsd Feb 22, 2026
2b973cf
test(resource-lifetime): add local and cross-tu ownership regression …
SizzleUnrlsd Feb 22, 2026
bc1b580
test(multi-tu): add split translation-unit integration fixture
SizzleUnrlsd Feb 22, 2026
f113e44
test(regression): add focused no-diagnostic coverage for edge cases
SizzleUnrlsd Feb 22, 2026
76e037a
chore(cleanup): remove obsolete generated artifacts and legacy docker…
SizzleUnrlsd Feb 22, 2026
51e780e
fix(ci): normalize GHCR owner to lowercase for docker image references
SizzleUnrlsd Feb 22, 2026
112e6bf
fix(action): replace unsupported hashFiles cache key with sha-based k…
SizzleUnrlsd Feb 22, 2026
af19226
test(harness): tolerate +/-1 location column drift in expectation mat…
SizzleUnrlsd Feb 22, 2026
318c105
ci(sarif): upload only when self-analysis sarif artifact exists
SizzleUnrlsd Feb 22, 2026
7b00b72
fix(action): avoid implicit compdb filtering when explicit sources ar…
SizzleUnrlsd Feb 22, 2026
b6a4806
fix(ci): use raw mode for single-file docker smoke tests without comp…
SizzleUnrlsd Feb 22, 2026
6bc19af
ci(tests): parallelize run_test with timeout and unbuffered logs
SizzleUnrlsd Feb 22, 2026
e594d18
fix(sarif): clamp SARIF region line/column to 1-based values
SizzleUnrlsd Feb 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
build/
build-*/
.git/
.github/
.vscode/
*.o
*.a
*.so
*.dylib
.venv/
__pycache__/
37 changes: 34 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ name: Build

on:
push:
branches: [ main, 3-feat-ci-add-build-workflow ]
branches:
- "**"
pull_request:
branches: [ main ]
branches:
- "**"
workflow_dispatch:

jobs:
build:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
permissions:
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -60,5 +65,31 @@ jobs:

- name: Test Stack Usage Analyzer (Linux/macOS)
if: runner.os == 'Linux' || runner.os == 'macOS'
timeout-minutes: 45
run: |
python3 run_test.py
TEST_JOBS="$(python3 -c 'import os; print(max(1, min(8, os.cpu_count() or 1)))')"
echo "Running run_test.py with ${TEST_JOBS} job(s)"
python3 -u run_test.py --jobs="${TEST_JOBS}"

- name: Self-analysis (analyze own source code)
if: runner.os == 'Linux'
run: |
mkdir -p artifacts
python3 scripts/ci/run_code_analysis.py \
--analyzer build/stack_usage_analyzer \
--compdb build/compile_commands.json \
--exclude build/_deps/ \
--base-dir ${{ github.workspace }} \
--sarif-out artifacts/self-analysis.sarif \
--json-out artifacts/self-analysis.json \
--fail-on error \
--analyzer-arg=--analysis-profile=fast \
--analyzer-arg=--resource-summary-cache-memory-only \
--analyzer-arg=--resource-model=models/resource-lifetime/generic.txt

- name: Upload SARIF to Code Scanning
if: runner.os == 'Linux' && always() && hashFiles('artifacts/self-analysis.sarif') != ''
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: artifacts/self-analysis.sarif
category: coretrace-self-analysis
119 changes: 119 additions & 0 deletions .github/workflows/publish-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
name: Publish Docker Images

on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Optional version tag override (example: v0.2.0)."
required: false
default: ""
push_latest:
description: "Also publish the latest tag."
required: false
type: boolean
default: true

permissions:
contents: read
packages: write

jobs:
publish:
name: Build and push images to GHCR
runs-on: ubuntu-24.04

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Resolve image names
id: images
shell: bash
run: |
owner_lower="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')"
echo "registry=ghcr.io" >> "${GITHUB_OUTPUT}"
echo "runtime=ghcr.io/${owner_lower}/coretrace-stack-analyzer" >> "${GITHUB_OUTPUT}"
echo "ci=ghcr.io/${owner_lower}/coretrace-stack-analyzer-ci" >> "${GITHUB_OUTPUT}"

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ steps.images.outputs.registry }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Compute image tags
id: tags
shell: bash
run: |
set -euo pipefail

short_sha="$(git rev-parse --short=12 HEAD)"

if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
version="${GITHUB_REF_NAME}"
elif [[ -n "${{ github.event.inputs.version }}" ]]; then
version="${{ github.event.inputs.version }}"
else
version="sha-${short_sha}"
fi

push_latest="false"
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
push_latest="true"
elif [[ "${{ github.event.inputs.push_latest }}" == "true" ]]; then
push_latest="true"
fi

runtime_base="${{ steps.images.outputs.runtime }}"
ci_base="${{ steps.images.outputs.ci }}"
runtime_tags="${runtime_base}:${version}"$'\n'"${runtime_base}:sha-${short_sha}"
ci_tags="${ci_base}:${version}"$'\n'"${ci_base}:sha-${short_sha}"

if [[ "${push_latest}" == "true" ]]; then
runtime_tags+=$'\n'"${runtime_base}:latest"
ci_tags+=$'\n'"${ci_base}:latest"
fi

{
echo "runtime_tags<<EOF"
echo "${runtime_tags}"
echo "EOF"
echo "ci_tags<<EOF"
echo "${ci_tags}"
echo "EOF"
echo "version=${version}"
echo "short_sha=${short_sha}"
} >> "${GITHUB_OUTPUT}"

- name: Build and push runtime image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.tags.outputs.runtime_tags }}
platforms: linux/amd64
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Build and push CI image
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.ci
push: true
tags: ${{ steps.tags.outputs.ci_tags }}
platforms: linux/amd64
build-args: |
CORETRACE_RUNTIME_IMAGE=${{ steps.images.outputs.runtime }}:${{ steps.tags.outputs.version }}
VERSION=${{ steps.tags.outputs.version }}
VCS_REF=${{ steps.tags.outputs.short_sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
171 changes: 171 additions & 0 deletions .github/workflows/test-ci-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: Test CI Integration

on:
push:
branches: [main]
paths:
- "Dockerfile"
- "action.yml"
- "scripts/ci/**"
- ".github/workflows/test-ci-integration.yml"
pull_request:
branches: [main]
workflow_dispatch:

jobs:
# =================================================================
# Job 1: Test the GitHub Action (composite action, local reference)
# =================================================================
test-github-action:
name: Test GitHub Action
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Run CoreTrace Stack Analyzer (action)
uses: ./
id: analysis
with:
sources: test/alloca/oversized-constant.c
fail-on: none
base-dir: ${{ github.workspace }}
sarif-file: action-results.sarif
json-file: action-results.json
upload-sarif: false

- name: Validate SARIF output
run: |
echo "=== Checking SARIF file exists ==="
test -f action-results.sarif || { echo "SARIF file missing!"; exit 1; }

echo "=== Validating JSON structure ==="
python3 -c "
import json, sys
with open('action-results.sarif') as f:
d = json.load(f)
assert d['version'] == '2.1.0', 'Wrong SARIF version'
assert len(d['runs']) > 0, 'No runs in SARIF'

run = d['runs'][0]
assert run['tool']['driver']['name'] == 'coretrace-stack-analyzer', 'Wrong tool name'

# Check that URIs are relative (no leading /)
for result in run.get('results', []):
for loc in result.get('locations', []):
uri = loc['physicalLocation']['artifactLocation']['uri']
assert not uri.startswith('/'), f'URI is absolute: {uri}'
print(f' OK: {uri}')

print('SARIF validation passed!')
"

- name: Validate JSON output
run: |
test -f action-results.json || { echo "JSON file missing!"; exit 1; }
python3 -c "
import json
with open('action-results.json') as f:
d = json.load(f)
assert 'diagnostics' in d, 'Missing diagnostics key'
assert len(d['diagnostics']) > 0, 'No diagnostics found'
print(f'JSON validation passed! Found {len(d[\"diagnostics\"])} diagnostic(s).')
"

# =================================================================
# Job 2: Test the Docker image
# =================================================================
test-docker:
name: Test Docker Image
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Resolve image reference
run: |
owner_lower="$(echo "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')"
echo "CORETRACE_IMAGE=ghcr.io/${owner_lower}/coretrace-stack-analyzer:latest" >> "$GITHUB_ENV"

- name: Pull Docker image
run: docker pull "${CORETRACE_IMAGE}"

- name: Run analyzer via Docker (SARIF)
run: |
docker run --rm -v "${{ github.workspace }}:/workspace" \
"${CORETRACE_IMAGE}" \
--raw \
/workspace/test/alloca/oversized-constant.c \
--format=sarif \
--base-dir=/workspace \
> docker-results.sarif

- name: Validate Docker SARIF output
run: |
echo "=== Checking SARIF file ==="
test -s docker-results.sarif || { echo "SARIF file empty!"; exit 1; }

python3 -c "
import json, sys
with open('docker-results.sarif') as f:
d = json.load(f)
assert d['version'] == '2.1.0', 'Wrong SARIF version'

run = d['runs'][0]
assert run['tool']['driver']['name'] == 'coretrace-stack-analyzer'

for result in run.get('results', []):
for loc in result.get('locations', []):
uri = loc['physicalLocation']['artifactLocation']['uri']
assert not uri.startswith('/'), f'URI is absolute: {uri}'
print(f' OK: {uri}')

print('Docker SARIF validation passed!')
"

- name: Run analyzer via Docker (JSON)
run: |
docker run --rm -v "${{ github.workspace }}:/workspace" \
"${CORETRACE_IMAGE}" \
--raw \
/workspace/test/alloca/oversized-constant.c \
--format=json \
> docker-results.json

- name: Validate Docker JSON output
run: |
python3 -c "
import json
with open('docker-results.json') as f:
d = json.load(f)
assert 'diagnostics' in d
assert len(d['diagnostics']) > 0
print(f'Docker JSON validation passed! Found {len(d[\"diagnostics\"])} diagnostic(s).')
"

- name: Run CI helper script via Docker
run: |
docker run --rm \
-v "${{ github.workspace }}:/workspace" \
--entrypoint python3 \
"${CORETRACE_IMAGE}" \
/usr/local/bin/run_code_analysis.py \
/workspace/test/alloca/oversized-constant.c \
--analyzer /usr/local/bin/stack_usage_analyzer \
--json-out /workspace/docker-ci-results.json \
--sarif-out /workspace/docker-ci-results.sarif \
--base-dir /workspace \
--fail-on none

- name: Validate CI script output
run: |
test -f docker-ci-results.sarif || { echo "CI SARIF missing!"; exit 1; }
test -f docker-ci-results.json || { echo "CI JSON missing!"; exit 1; }
echo "CI script Docker test passed!"
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,13 @@ set(STACK_ANALYZER_SOURCES
src/analysis/InputPipeline.cpp
src/analysis/InvalidBaseReconstruction.cpp
src/analysis/MemIntrinsicOverflow.cpp
src/analysis/ResourceLifetimeAnalysis.cpp
src/analysis/SizeMinusKWrites.cpp
src/analysis/StackBufferAnalysis.cpp
src/analysis/StackComputation.cpp
src/analysis/StackPointerEscape.cpp
src/analysis/StackPointerEscapeModel.cpp
src/analysis/StackPointerEscapeResolver.cpp
src/analysis/UninitializedVarAnalysis.cpp
src/report/ReportSerialization.cpp
src/mangle.cpp
Expand Down
Loading
Loading