diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 2c3db91..02d9e55 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -4,9 +4,16 @@ on: push: pull_request: +# One runner: cancel the previous push's jobs (avoids a stuck ASan job +# blocking every later commit). +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: linux: runs-on: ubuntu-latest + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -38,6 +45,7 @@ jobs: sanitizers: runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v4 - name: Install dependencies @@ -48,10 +56,22 @@ jobs: $SUDO apt-get install -y --no-install-recommends \ build-essential pkg-config libcurl4-openssl-dev libncurses-dev - name: ASan + UBSan - run: make asan + timeout-minutes: 10 + env: + # Docker runners without SYS_PTRACE can spin forever on + # AddressSanitizer:DEADLYSIGNAL; keep the handler shallow and + # hard-cap wall time so the single runner is not wedged. + ASAN_OPTIONS: abort_on_error=1:halt_on_error=1:detect_leaks=0:use_sigaltstack=0 + UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1 + run: | + if ! timeout -s KILL 480 make asan; then + echo "::error::make asan failed or timed out after 8m (if the log is only DEADLYSIGNAL, give the runner SYS_PTRACE / seccomp=unconfined)" + exit 1 + fi musl: runs-on: ubuntu-latest + timeout-minutes: 30 container: alpine:3.20 steps: - name: Install dependencies @@ -71,6 +91,7 @@ jobs: macos: if: ${{ vars.HAVE_MACOS_RUNNER == 'true' }} runs-on: macos-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v4 - name: Install dependencies diff --git a/src/sandbox_exec.c b/src/sandbox_exec.c index 9050c93..7997d6b 100644 --- a/src/sandbox_exec.c +++ b/src/sandbox_exec.c @@ -566,9 +566,10 @@ static void sc_rewrite(int pid, const char *in, char *out, size_t n) { static int sc_abs_ok(const sc_state_t *s, const char *full, int follow, int strict) { char path[OS_PATH_MAX], real[OS_PATH_MAX], loc[2 * OS_PATH_MAX + 2]; - if (strlen(full) >= sizeof(path)) + size_t flen = strlen(full); + if (flen >= sizeof(path)) return 0; - snprintf(path, sizeof(path), "%s", full); + memcpy(path, full, flen + 1); size_t n = strlen(path); while (n > 1 && path[n - 1] == '/') path[--n] = 0;