Skip to content

vendor-libreoffice-20260822 (headless LibreOffice, macOS arm64, r3)

Choose a tag to compare

@HeavenllyDemon HeavenllyDemon released this 22 Aug 02:10
· 348 commits to main since this release

Prebuilt, privacy-scrubbed headless LibreOffice engine for macOS arm64 — vendored dependency for
the Norma app, not an app release itself (--latest=false; does not affect the app's release
lineage or its Sparkle appcast).

What this is

A native macOS arm64 build of LibreOffice/core @ 11482c8f71bc76ed6260bc03b1576a52a788ab4f
with --enable-headless (the svp/headless VCL backend — the same shape LibreOffice's own iOS
port uses). Same commit, same configure flags, same build as -r2 — this asset changes only the
two items below. Zero source patches anywhere in this build.

Why -r3

Two disclosed changes on top of -r2, both from the same already-built core/instdir/ (no
rebuild):

  1. The OOXML export fix. -r2's saveAs to .xlsx crashed the whole helper process —
    libuno_sal.dylib.3's text-encoding subsystem lazily dlopens libsal_textenclo.dylib by
    name the first time a full charset lookup is needed (e.g. an Excel font record's Windows
    charset ID), and abort()s when the load fails. That dylib is absent from -r2's 66-dylib
    Frameworks/ because it is reached only through a runtime dlopen, never a link-time
    dependency — -r2's closure recipe (a DYLD_PRINT_LIBRARIES trace of an import+paint-only
    workload, plus a one-level otool -L safety net) had no way to see it. -r3 adds this one
    file — a verbatim cp -pP from the identical instdir every other dylib already came from,
    re-scanned for privacy independently, not assumed clean by inheritance. Verified before
    packaging (a standalone LOK harness, product-set + this one dylib, nothing else changed):
    gate.xlsx now saves successfully (real output file, clean exit); gate.pptx is unaffected
    (already worked, still works). gate.docx still does not save — the missing-dylib abort is
    gone (no crash, reproduced on two independent fresh profiles), but a different, still-open
    Writer/OOXML-export defect surfaces instead: a clean, caught SVSTREAM_WRITE_ERROR
    (ERRCODE_IO_CANTWRITE) inside SfxBaseModel::impl_store. Unrelated to the charset-table gap
    this asset fixes; disclosed, not chased further here.

  2. A tar-container privacy fix -r2 didn't have. Measured directly against the live,
    currently-published -r2 asset (cold-downloaded, SHA-256-matched to its pin): the tarball's own
    per-entry headers record the packaging account's macOS username and primary group, via
    bsdtar's default owner-name recording — independent of, and not caught by, -r2's own
    file-content byte-scan (which read extracted file bytes, never the tar's own header bytes).
    -r3's tar is built with explicit owner/group suppression (tar --uid 0 --gid 0 --uname '' --gname ''); see the Privacy scan section below for the verification. The live -r2 asset was
    not modified or re-uploaded — a GitHub release asset is maintainer-replaceable at the same
    URL, and re-publishing scrubbed bytes under the same name is exactly the silent-swap hazard this
    repo's own fetch-libreoffice.ts header warns against. Flagged here as an open item for whoever
    owns this asset's lifecycle to consider once -r3 is the pinned, fetched asset.

Engine-wise, nothing else changed: all six format fixtures render pixel-identical (raw SHA-256 of
the paintTile output) to -r2/the original build. Adding one dylib and fixing tar metadata
changes zero pixels.

Contents

  • product-set/ — the runtime closure: Frameworks/ (67 of 248 possible dylibs — -r2's trim
    plus this release's one added file) + Resources/ (LibreOffice's config/UI-resource tree,
    shipped whole, unchanged from -r2).
  • LICENSES/ — per-upstream-project license texts, plus MANIFEST.md (updated: 67 dylibs, the
    new file is the same already-covered libreoffice-core module/license, no new upstream
    project).
  • VERSION-PIN — the exact configure flags, commit, build facts an embedder needs, the R3
    ADDENDUM documenting both changes above in full (including the verified install-name/link shape
    of the added dylib — matches its siblings, no patching needed), and the six-fixture pixel-hash
    pins (unchanged from -r2).

Using this

Ships adhoc/linker-signed, as LibreOffice's own build produces it — this tarball does not sign
or notarize anything. An embedding application is responsible for re-signing these dylibs with its
own Developer ID identity (and hardened runtime, if applicable) at its own build time — Norma's own
embed phase does this, counting Mach-Os dynamically rather than assuming a fixed number, so the
67th dylib needs no build-script change.

See VERSION-PIN inside the archive for the dlopen entry point, the required _Exit(0) teardown
pattern, and the fontconfig caveat — all unchanged from -r2.

Privacy scan — exact command and full result

Reused this repo's own local-only identity guard (the same mechanism scripts/release.ts's §11b
publish gate uses for app releases) — ~/norma-private/git-hooks/name-guard.sh artifacts <path>,
patterns not reproduced here since this file ships inside a public release (the guard is deliberately
local-only, outside every repository, for exactly that reason).

Scanned separately, before compression:

  • The added dylib alone (libsal_textenclo.dylib): clean.
  • product-set/Frameworks/ whole (all 67 dylibs): clean.
  • product-set/Resources/ minus one already-known, byte-verified-unchanged-from--r2 file
    (liblangtag/language-subtag-registry.xml, IANA's language-subtag registry — a natural-language
    collision, <description>Como Karim</description>, a real registered language name (ISO 639-3
    cfg), not an identity leak; this exact file is already a standing exclusion in this repo's own
    release-lib.ts NAME_SCAN_EXCLUSIONS for the identical reason): clean.
  • LICENSES/: clean.
  • VERSION-PIN: clean.
  • The final, uncompressed .tar (owner-suppressed): exactly one hit, independently verified
    byte-for-byte to be the same IANA registry collision above (single match, same description
    string, same file) — not a new leak, not identity-bearing.
  • The .tar.zst was verified by decompression round-trip (SHA-256-identical to the already-scanned
    .tar), not re-scanned directly — compression would hide any string from a byte scan the same
    way it would for a .zip/.dmg, so the meaningful gate is the uncompressed archive.

Zero identity hits anywhere in this asset.