From 09cdc8098672a66e89eef24b4dd69aa8e65c6d2b Mon Sep 17 00:00:00 2001 From: Eremey Valetov Date: Sat, 13 Jun 2026 07:53:46 -0400 Subject: [PATCH] ci: build the DOS (DJGPP) target and consolidate the toolchain file A new Linux job installs the andrewwutw DJGPP v3.4 cross-toolchain (gcc 12.2.0, sha256-pinned), cross-compiles uc2.exe with cmake/djgpp.cmake, and verifies the result is a DJGPP go32 DOS executable. The DOS build had no CI coverage and could regress silently. The repo carried two diverged DJGPP toolchain files. djgpp.cmake (referenced by the build docs) forces -nostdinc with explicit DJGPP include paths, so it builds cleanly even on hosts where /usr/include would otherwise leak past the cross-compiler. djgpp-toolchain.cmake (previously referenced by the README) relied on the cross-gcc finding its own headers and broke in that case. Keep djgpp.cmake as the single toolchain file, point the README and roadmap at it, and drop djgpp-toolchain.cmake. --- .github/workflows/build.yml | 31 +++++++++++++++++++++ ROADMAP.md | 14 +++++++++- cmake/README-djgpp.md | 12 ++++---- cmake/djgpp-toolchain.cmake | 55 ------------------------------------- 4 files changed, 51 insertions(+), 61 deletions(-) delete mode 100644 cmake/djgpp-toolchain.cmake diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 179526a..d0eb7f0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,3 +71,34 @@ jobs: run: cmake --build build -j - name: Round-trip test run: ctest --test-dir build --output-on-failure -R libarchive_roundtrip + + djgpp: + runs-on: ubuntu-latest + name: DOS (DJGPP) + env: + DJGPP_URL: https://github.com/andrewwutw/build-djgpp/releases/download/v3.4/djgpp-linux64-gcc1220.tar.bz2 + DJGPP_SHA256: 8464f17017d6ab1b2bb2df4ed82357b5bf692e6e2b7fee37e315638f3d505f00 + # Keep host include dirs out of the cross-compiler's search path in + # every step (the toolchain file also forces -nostdinc, but a stray + # CPATH on the runner would otherwise leak glibc headers). + CPATH: '' + CPLUS_INCLUDE_PATH: '' + steps: + - uses: actions/checkout@v4 + - name: Install DJGPP cross-toolchain + run: | + curl -fsSL -o djgpp.tar.bz2 "$DJGPP_URL" + echo "${DJGPP_SHA256} djgpp.tar.bz2" | sha256sum -c - + sudo tar xjf djgpp.tar.bz2 -C /opt # -> /opt/djgpp + - name: Configure (DJGPP toolchain) + run: | + cmake -B build-dos \ + -DCMAKE_TOOLCHAIN_FILE=cmake/djgpp.cmake \ + -DDJGPP_ROOT=/opt/djgpp -DCMAKE_BUILD_TYPE=Release + - name: Build + run: cmake --build build-dos -j + - name: Verify DOS executable + run: | + file build-dos/cli/uc2.exe + file build-dos/cli/uc2.exe | grep -q "DJGPP go32 DOS extender" \ + || { echo "uc2.exe is not a DJGPP DOS executable"; exit 1; } diff --git a/ROADMAP.md b/ROADMAP.md index 7bad5aa..756a4a0 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -105,7 +105,7 @@ No mainstream archiver offers post-quantum encryption. ## Phase 6: DOS / FreeDOS / Retro-Computing -- [x] DJGPP cross-compilation toolchain: `cmake/djgpp-toolchain.cmake` +- [x] DJGPP cross-compilation toolchain: `cmake/djgpp.cmake` builds `uc2.exe` against the prebuilt DJGPP gcc 7.2 / 12.2 from `andrewwutw/build-djgpp`. Output is a 32-bit DPMI DOS executable (MZ + COFF + go32 stub). See `cmake/README-djgpp.md` for the @@ -294,3 +294,15 @@ Bobrowski already shipped prototypes; update for UC2 v3. Found debugging extraction on sdf.org (NetBSD 10) but reproducible everywhere. New regression test: cli_bigfile. Follow-up filed: bf73896 (ftell offsets >4GB truncate silently; P2). + +- 2026-06-13: DOS build now has CI coverage (DJGPP v3.4 toolchain, + sha-pinned; builds uc2.exe via cmake/djgpp.cmake; git-bug 9379647). + Consolidated the two DJGPP toolchain files onto djgpp.cmake and + removed the redundant djgpp-toolchain.cmake. +- 2026-06-13: Damaged-archive decode hardening (git-bug f049d6d): + decompress_block match-length overflow guard (runtime check + replacing an NDEBUG assert), decompress_cdir end-bounding, and a + CLI handle/FILE leak fix on the cdir-error path. A prefix-sweep + fuzzer drove the fixes; a residual rare cdir-parser OOB it surfaces + is tracked for a systematic hardening + fuzzing pass (git-bug + 69e8e52). diff --git a/cmake/README-djgpp.md b/cmake/README-djgpp.md index ec12e22..f96b3fe 100644 --- a/cmake/README-djgpp.md +++ b/cmake/README-djgpp.md @@ -31,7 +31,7 @@ the bundled `cwsdpmi.exe` extender (or any DPMI host). ```sh unset CPATH CPLUS_INCLUDE_PATH cmake -B build-djgpp \ - -DCMAKE_TOOLCHAIN_FILE=cmake/djgpp-toolchain.cmake \ + -DCMAKE_TOOLCHAIN_FILE=cmake/djgpp.cmake \ -DDJGPP_ROOT=/opt/djgpp cmake --build build-djgpp ``` @@ -42,7 +42,9 @@ plus `cwsdpmi.exe` (shipped with DJGPP at ## Status -- Compiles clean against DJGPP gcc 7.2.0 and 12.2.0. +- Compiles clean against the DJGPP gcc 12.2.0 toolchain (the + `cmake/djgpp.cmake` include paths are pinned to that version; the + CI job and the andrewwutw v3.4 release both use 12.2.0). - Library (`libuc2.a`) builds without changes. - CLI uses the DOS compat layer in `cli/src/compat/compat_dos.c` for the BSD `err.h` and POSIX `fnmatch` shims. @@ -69,9 +71,9 @@ not installed. ## Notes -- The toolchain file forces `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` - because the compiler check would otherwise try to execute a DOS .exe - on the host kernel and fail. +- The toolchain sets `CMAKE_SYSTEM_NAME Generic` and `-nostdinc` with + explicit DJGPP include paths, so the compiler check links a test + binary (rather than running one) and host headers never leak in. - DJGPP's `unistd.h` provides POSIX-shaped APIs; most of the existing source compiles unchanged. The library has no DOS-specific code paths. diff --git a/cmake/djgpp-toolchain.cmake b/cmake/djgpp-toolchain.cmake deleted file mode 100644 index 9107591..0000000 --- a/cmake/djgpp-toolchain.cmake +++ /dev/null @@ -1,55 +0,0 @@ -# CMake toolchain file for DJGPP cross-compile (DOS / FreeDOS). -# -# Usage: -# cmake -B build-djgpp -DCMAKE_TOOLCHAIN_FILE=cmake/djgpp-toolchain.cmake -# cmake --build build-djgpp -# -# Requires the DJGPP cross-toolchain on PATH or at DJGPP_ROOT. The standard -# layout from andrewwutw/build-djgpp and the djfdyuruiry/djgpp docker image -# is /usr/local/bin/djgpp/. Override with -DDJGPP_ROOT= if installed -# elsewhere. - -set(CMAKE_SYSTEM_NAME Generic) # bare DJGPP DOS, no OS abstractions -set(CMAKE_SYSTEM_PROCESSOR i386) - -# Project source uses `if(DJGPP)` to gate the DOS compat layer (cli/src/ -# compat/compat_dos.c, sys-include/dos shim). Set the variable up front -# so those guards activate. -set(DJGPP TRUE) - -# Locate the toolchain prefix. -if(NOT DEFINED DJGPP_ROOT) - if(EXISTS /usr/local/bin/djgpp) - set(DJGPP_ROOT /usr/local/bin/djgpp) - elseif(EXISTS /opt/djgpp) - set(DJGPP_ROOT /opt/djgpp) - endif() -endif() - -if(DEFINED DJGPP_ROOT AND EXISTS ${DJGPP_ROOT}) - set(_DJGPP_BIN ${DJGPP_ROOT}/bin) -else() - set(_DJGPP_BIN "") -endif() - -set(CMAKE_C_COMPILER ${_DJGPP_BIN}/i586-pc-msdosdjgpp-gcc) -set(CMAKE_CXX_COMPILER ${_DJGPP_BIN}/i586-pc-msdosdjgpp-g++) -set(CMAKE_AR ${_DJGPP_BIN}/i586-pc-msdosdjgpp-ar CACHE FILEPATH "") -set(CMAKE_RANLIB ${_DJGPP_BIN}/i586-pc-msdosdjgpp-ranlib CACHE FILEPATH "") -set(CMAKE_STRIP ${_DJGPP_BIN}/i586-pc-msdosdjgpp-strip CACHE FILEPATH "") - -if(DEFINED DJGPP_ROOT) - set(CMAKE_FIND_ROOT_PATH ${DJGPP_ROOT}/i586-pc-msdosdjgpp) -endif() -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) - -# DJGPP can produce static binaries; tests run inside DOSBox-X. -set(CMAKE_EXE_LINKER_FLAGS_INIT "") - -# CMake's compiler check tries to build a test binary. DJGPP-produced -# .exe binaries are valid COFF executables that the host kernel will -# refuse to run, so use STATIC_LIBRARY mode. -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)