Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
28 changes: 14 additions & 14 deletions .github/workflows/ost-source-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ jobs:
if: ${{ matrix.hosted }}
shell: bash
run: echo "::notice title=OpenStrata hosted-runner usage::This job uses GitHub-hosted infrastructure. Private repositories may incur GitHub Actions usage charges. Review repository billing and Actions usage settings."
- name: Bootstrap ost 0.23.19 (pinned release asset, checksum-verified)
- name: Bootstrap ost 0.23.20 (pinned release asset, checksum-verified)
if: ${{ matrix.hosted }}
shell: bash
run: |
Expand All @@ -250,7 +250,7 @@ jobs:
*) : ;;
esac
asset="ost-cli-${triple}.${ext}"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.23.19"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.23.20"
curl -fsSLo "$asset" "$base/$asset"
curl -fsSLo "$asset.sha256" "$base/$asset.sha256"
actual="$( (command -v sha256sum > /dev/null && sha256sum "$asset" || shasum -a 256 "$asset") | cut -d' ' -f1 )"
Expand Down Expand Up @@ -284,7 +284,7 @@ jobs:
echo "$exported_path" >> "$GITHUB_PATH"
json_executable="$(printf '%s' "$executable" | sed 's/\\/\\\\/g; s/"/\\"/g')"
json_exported_path="$(printf '%s' "$exported_path" | sed 's/\\/\\\\/g; s/"/\\"/g')"
printf '{"schema":1,"pinned_version":"%s","asset":"%s","sha256":"%s","executable":"%s","exported_path":"%s"}\n' "0.23.19" "$asset" "$actual" "$json_executable" "$json_exported_path" > .ost-ci/bootstrap.json
printf '{"schema":1,"pinned_version":"%s","asset":"%s","sha256":"%s","executable":"%s","exported_path":"%s"}\n' "0.23.20" "$asset" "$actual" "$json_executable" "$json_exported_path" > .ost-ci/bootstrap.json
- name: Check ost is available and record its version
shell: bash
run: |
Expand All @@ -297,8 +297,8 @@ jobs:
fi

echo "$version"
if [ "${{ matrix.hosted }}" = "true" ] && [ "$version" != "ost 0.23.19" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.23.19', got '$version'" ; exit 1
if [ "${{ matrix.hosted }}" = "true" ] && [ "$version" != "ost 0.23.20" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.23.20', got '$version'" ; exit 1
fi
printf '{"schema":1,"ost_version":"%s"}\n' "$version" > .ost-ci/ost-version.json
- name: Validate the CI manifest
Expand All @@ -310,7 +310,7 @@ jobs:
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .ost-ci-home/artifacts
key: ost-registry-0.23.19-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
key: ost-registry-0.23.20-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
- name: Pull the pinned runtime SDK from its remote reference
if: ${{ matrix.runtime_remote != '' }}
shell: bash
Expand Down Expand Up @@ -360,7 +360,7 @@ jobs:
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .ost-ci-home/artifacts
key: ost-registry-0.23.19-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
key: ost-registry-0.23.20-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
- name: Install the host packages this runtime needs to be consumed
if: ${{ matrix.host_packages_apt != '' || matrix.host_packages_brew != '' }}
shell: bash
Expand Down Expand Up @@ -522,7 +522,7 @@ jobs:
if: ${{ matrix.hosted }}
shell: bash
run: echo "::notice title=OpenStrata hosted-runner usage::This job uses GitHub-hosted infrastructure. Private repositories may incur GitHub Actions usage charges. Review repository billing and Actions usage settings."
- name: Bootstrap ost 0.23.19 (pinned release asset, checksum-verified)
- name: Bootstrap ost 0.23.20 (pinned release asset, checksum-verified)
if: ${{ matrix.hosted }}
shell: bash
run: |
Expand All @@ -540,7 +540,7 @@ jobs:
*) : ;;
esac
asset="ost-cli-${triple}.${ext}"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.23.19"
base="https://github.com/animu-sphere/open-strata/releases/download/v0.23.20"
curl -fsSLo "$asset" "$base/$asset"
curl -fsSLo "$asset.sha256" "$base/$asset.sha256"
actual="$( (command -v sha256sum > /dev/null && sha256sum "$asset" || shasum -a 256 "$asset") | cut -d' ' -f1 )"
Expand Down Expand Up @@ -574,7 +574,7 @@ jobs:
echo "$exported_path" >> "$GITHUB_PATH"
json_executable="$(printf '%s' "$executable" | sed 's/\\/\\\\/g; s/"/\\"/g')"
json_exported_path="$(printf '%s' "$exported_path" | sed 's/\\/\\\\/g; s/"/\\"/g')"
printf '{"schema":1,"pinned_version":"%s","asset":"%s","sha256":"%s","executable":"%s","exported_path":"%s"}\n' "0.23.19" "$asset" "$actual" "$json_executable" "$json_exported_path" > .ost-ci/bootstrap.json
printf '{"schema":1,"pinned_version":"%s","asset":"%s","sha256":"%s","executable":"%s","exported_path":"%s"}\n' "0.23.20" "$asset" "$actual" "$json_executable" "$json_exported_path" > .ost-ci/bootstrap.json
- name: Check ost is available and record its version
shell: bash
run: |
Expand All @@ -587,8 +587,8 @@ jobs:
fi

echo "$version"
if [ "${{ matrix.hosted }}" = "true" ] && [ "$version" != "ost 0.23.19" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.23.19', got '$version'" ; exit 1
if [ "${{ matrix.hosted }}" = "true" ] && [ "$version" != "ost 0.23.20" ]; then
echo "::error title=ost bootstrap::expected 'ost 0.23.20', got '$version'" ; exit 1
fi
printf '{"schema":1,"ost_version":"%s"}\n' "$version" > .ost-ci/ost-version.json
- name: Validate the CI manifest
Expand All @@ -600,7 +600,7 @@ jobs:
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .ost-ci-home/artifacts
key: ost-registry-0.23.19-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
key: ost-registry-0.23.20-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
- name: Pull the pinned runtime SDK from its remote reference
if: ${{ matrix.runtime_remote != '' }}
shell: bash
Expand Down Expand Up @@ -650,7 +650,7 @@ jobs:
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: .ost-ci-home/artifacts
key: ost-registry-0.23.19-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
key: ost-registry-0.23.20-${{ runner.os }}-${{ runner.arch }}-${{ matrix.name }}-${{ matrix.runtime_artifact }}
- name: Install the host packages this runtime needs to be consumed
if: ${{ matrix.host_packages_apt != '' || matrix.host_packages_brew != '' }}
shell: bash
Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ semantic versioning for tagged releases.
### Changed

- The build and verification toolchain moves from OpenStrata **0.22.10 to
0.23.19** (`openstrata.ci.yaml` bootstrap and the regenerated
0.23.20** (`openstrata.ci.yaml` bootstrap and the regenerated
`ost-source-ci.yml`; the release lane derives the same pin through
`scripts/release.py`). The regenerated workflow builds its OpenUSD
requirement arguments with POSIX `set --` instead of a bash array, and adds
Expand All @@ -59,6 +59,9 @@ semantic versioning for tagged releases.

### Fixed

- `gaussian-sog`: a bundled `meta.json` whose declared expanded size exceeds
4 MiB is rejected before allocation and inflation in full and metadata-only
reads.
- `scripts/benchmark_import.py`: on Linux, peak resident memory is now read
from the process's own `VmHWM`. `ru_maxrss` starts from the parent's
resident size at fork and survives exec, so a large launching process
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ ctest --test-dir build/default --output-on-failure
```

The repo is dual-mode: with
[OpenStrata](https://github.com/animu-sphere/open-strata) `ost` 0.23.19 the
[OpenStrata](https://github.com/animu-sphere/open-strata) `ost` 0.23.20 the
same tree gets the full verification ladder, packaging, and viewer tooling —
see [BUILDING.md](docs/guides/BUILDING.md):

Expand Down
11 changes: 7 additions & 4 deletions docs/guides/BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ installing a packaged release is in [INSTALL.md](INSTALL.md).

## OpenStrata path (primary)

Requirements: `ost` 0.23.19 (the version the CI lane bootstraps; the last
locally verified baseline below is 0.22.10), a real `cy2026` / `usd`
OpenStrata runtime, OpenUSD `>=26.05,<27.0`, a C++17 compiler. The verified local runtime is OpenUSD 26.08
Requirements: `ost` 0.23.20 (the CI and local verification baseline), a real
`cy2026` / `usd` OpenStrata runtime, OpenUSD `>=26.05,<27.0`, and a C++17
compiler. The verified local runtime is OpenUSD 26.08
on Windows x86-64 / MSVC 143 / Python 3.13 — the same digest-pinned artifact
the CI cells pull, so `ost plugin test` reports `runtime source is 'artifact'
(reproducible)` locally rather than an uncertified local build:
Expand Down Expand Up @@ -36,11 +36,14 @@ Windows runs to L4 in hosted CI and to L5 locally; see
checked-in GitHub Actions workflows after matrix changes:

```sh
ost ci generate github --force
ost ci generate github --force --out .github/workflows/ost-source-ci.yml
```

### Viewing and converting assets

With `ost` 0.23.20, `ost plugin view` loads the plugin from the selected
target's managed stage when available. Use a runtime that includes `usdview`.

```powershell
ost plugin view plugins\gaussian-ply "C:\path\to\scene.ply"
ost plugin run plugins\gaussian-ply -- usdcat --flatten --skipSourceFileComment --usdFormat usdc --out scene.usd scene.ply
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ plugins/<bundle>/dist/plugins/<bundle>/<version>/<target>/

alongside `manifest.json`, `sbom.spdx.json`, and `SHA256SUMS`.

The current package-origin run passes discovery, read, and stage-open checks
for all three bundles on the Windows 0.22.10 baseline. The source-workspace L5
checks also pass locally. Hosted release dry-run
On Windows, OpenStrata 0.23.20 passes source and package-origin verification
through L5 for all three bundles. Two consecutive packaging runs produce the
same aggregate archive SHA-256. The v0.5.1 hosted release dry-run
[#34996154493](https://github.com/animu-sphere/usd-3dgs-plugins/actions/runs/34996154493)
passed package-origin verification at the declared Windows L4 cap and at L5 on
macOS arm64 and Linux after the OpenUSD 26.08 re-pin.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/CAPABILITY_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,6 @@ This table describes the current tree. Planned capabilities belong in the
| Source L0-L5 verification | supported; locally green |
| Target-specific package | supported; locally generated and tested |
| Package-origin L0-L4 | supported; locally green |
| Package-origin L5 | supported since the OST 0.20.0 pin; on the 0.22.10 pin it executes and passes locally for all three bundles (it was skipped on 0.18.0, which did not stage the golden). Hosted release dry-run [#34996154493](https://github.com/animu-sphere/usd-3dgs-plugins/actions/runs/34996154493) passed package-origin L5 on macOS/Linux and the declared Windows L4 cap |
| Package-origin L5 | supported since OST 0.20.0; passes for all three bundles on local Windows with OST 0.23.20. The v0.5.1 hosted release dry-run [#34996154493](https://github.com/animu-sphere/usd-3dgs-plugins/actions/runs/34996154493) passed package-origin L5 on macOS/Linux and the declared Windows L4 cap |
| Windows/macOS/Linux generated CI | supported and validated by hosted release dry-run [#34996154493](https://github.com/animu-sphere/usd-3dgs-plugins/actions/runs/34996154493): Windows L4, macOS arm64 L5, and Linux L5 |
| Hydra Gaussian renderer | unsupported here; owned by the sibling project [hydra-merlin](https://github.com/animu-sphere/hydra-merlin) ([release plan](../roadmap/release-plan.md) v0.9.0) |
8 changes: 7 additions & 1 deletion docs/reference/IMPORT_LIMITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ single import into an unbounded allocation request.
| SPZ source file size | 1 GiB | SPZ v1-v3 |
| SPZ extension records | 64 MiB | SPZ v1-v3 |

For bundled SOG, full and metadata-only reads check the declared expanded size
of `meta.json` before allocating its extraction buffer or inflating the entry.

The readers also use checked multiplication and allocation helpers for model
arrays, reject zero-count clouds, require every SOG plane to be present and
large enough for the declared count, reject duplicate SOG plane names and ZIP
Expand Down Expand Up @@ -55,7 +58,7 @@ message naming the budget that fired.
| Budget | Hostile input | Expected |
| --- | --- | --- |
| Declared Gaussian count | `gaussian-ply/.../too-many-gaussians.ply`, `gaussian-spz/.../shared-limit-v2.spz`, `gaussian-sog/.../too-many-gaussians/meta.json` | `GSPLY-E019`, `GSPZ-E015`, `GSSOG-E016` |
| SOG `meta.json` size | 4 MiB + 1 byte unbundled `meta.json`, written at test time | `GSSOG-E016` (full and metadata-only reads) |
| SOG `meta.json` size | `zip-metadata-over-limit.sog` declares 4 MiB + 1 byte; unbundled `meta.json` of the same size, written at test time | `GSSOG-E016` (full and metadata-only reads) |
| SOG JSON nesting depth / value tokens | in-memory documents one past each bound | `ParseJson` rejection (`GSSOG-E005` when reached through `meta.json`) |
| SOG ZIP entries | `too-many-entries.sog` (65 entries) | `GSSOG-E016` |
| SOG ZIP entry size | `oversized-entry.sog` (one entry declaring 600 MiB) | `GSSOG-E016` |
Expand All @@ -70,6 +73,9 @@ message naming the budget that fired.
| SOG companion input size, directory loader | `quats.webp` grown to 512 MiB + 1 byte at test time (reader `TestOversizedUnbundledCompanion`) | `GSSOG-E016`; the metadata-only read still succeeds |
| SOG companion input size, asset resolver | same, opened through `ArDefaultResolver` (`test_gaussian_sog_resolver.py` `case_oversized_companion`) | `GSSOG-E016` |

Full and metadata-only reads also accept bundled metadata at exactly 4 MiB and
archives with exactly 64 entries.

The real-size rows grow a small file with `resize_file` / `truncate`, which
leaves the tail unwritten (a sparse hole on Linux and macOS, an unwritten
extension on NTFS). Nothing is committed, and each reader refuses the file
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/SUPPORTED_CONFIGURATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ support contract.

| Item | Contract |
| --- | --- |
| OpenStrata | 0.23.19 in CI; the last locally verified baseline is 0.22.10 (v0.5.1 was built with 0.22.10, v0.5.0 with 0.20.0, v0.1.0-v0.4.0 with 0.18.0) |
| OpenStrata | 0.23.20 in CI and local verification (v0.5.1 was built with 0.22.10, v0.5.0 with 0.20.0, v0.1.0-v0.4.0 with 0.18.0) |
| OpenUSD tolerated range | `>=26.05,<27.0` |
| OpenUSD exercised locally | 26.08 (26.05 through v0.5.0) |
| OpenUSD in the pinned CI runtimes | 26.08, tag `v26.08` |
Expand Down
9 changes: 5 additions & 4 deletions openstrata.ci.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# OpenStrata CI support matrix for usd-3dgs-plugins.
#
# This file is the CI contract. Regenerate .github/workflows/ost-*.yml with
# `ost ci generate github` after changing it. `.github/workflows/release.yml`
# This file is the CI contract. Regenerate the source workflow with
# `ost ci generate github --force --out .github/workflows/ost-source-ci.yml`.
# `.github/workflows/release.yml`
# is hand-authored and outside the generator's contract, but it is not outside
# this file's: scripts/release.py derives the release matrix from the cells
# below, so a pin moved here moves both lanes.
Expand All @@ -23,7 +24,7 @@
# the `sdk` layout profile, carrying an SPDX SBOM and SLSA/in-toto
# provenance, and verify `trust: attested` -- which is what the
# `--require-sbom --require-provenance` gate the generator renders demands.
# Consuming them needs ost >= 0.22.6; the bootstrap below is 0.23.19. The OCI
# Consuming them needs ost >= 0.22.6; the bootstrap below is 0.23.20. The OCI
# manifest digest is not stable across republishes, and `runtime_artifact`
# does not stay put either: re-pin both from the producer's push output.
# Rechecked 2026-11-03 for the 0.23.19 bootstrap: the registry still serves
Expand All @@ -43,7 +44,7 @@ schema: 1

bootstrap:
ost:
version: "0.23.19"
version: "0.23.20"
repository: animu-sphere/open-strata

runners:
Expand Down
3 changes: 3 additions & 0 deletions plugins/gaussian-sog/src/io/SogReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ class ZipArchive {
"-byte bound "
"this reader will allocate for one entry.");
}
if (name == kMetaEntryName && stat.m_uncomp_size > kMaxMetadataBytes) {
return RejectOversizedMetadata(stat.m_uncomp_size, error);
}
if (stat.m_uncomp_size > static_cast<std::uint64_t>(
std::numeric_limits<std::size_t>::max())) {
return fail(diag::kImportLimitExceeded,
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions plugins/gaussian-sog/tests/test_gaussian_sog_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
# Container budgets (IMPORT_LIMITS.md): each is refused from what it
# declares, before a buffer is sized from it.
"too-many-entries.sog": "GSSOG-E016",
"zip-metadata-over-limit.sog": "GSSOG-E016",
"oversized-entry.sog": "GSSOG-E016",
"oversized-expansion.sog": "GSSOG-E016",
"oversized-plane-dimensions.sog": "GSSOG-E016",
Expand Down
20 changes: 20 additions & 0 deletions plugins/gaussian-sog/tests/test_gaussian_sog_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,21 @@ void TestMalformedContainers()
// (an ASan build of this test would otherwise trip on the allocation).
void TestContainerBudgets()
{
const gssog::SogReader reader;
for (const char* name :
{"zip-metadata-at-limit.sog", "zip-entry-count-at-limit.sog"}) {
gssog::SogDocument document;
gssog::SogMetadata metadata;
std::string error;
CHECK(reader.Read(Fixture(name), &document, &error));
CHECK(reader.ReadMetadata(Fixture(name), &metadata, &error));
CHECK(document.metadata.gaussianCount == 1);
CHECK(metadata.gaussianCount == 1);
}

ExpectCodeWith("zip-metadata-over-limit.sog",
gssog::diag::kImportLimitExceeded,
"meta.json is 4194305 bytes");
ExpectCodeWith("too-many-entries.sog", gssog::diag::kImportLimitExceeded,
"-entry limit");
ExpectCodeWith("oversized-entry.sog", gssog::diag::kImportLimitExceeded,
Expand All @@ -598,6 +613,11 @@ void TestContainerBudgets()
// archive a full read refuses.
gssog::SogMetadata metadata;
std::string error;
CHECK(!reader.ReadMetadata(Fixture("zip-metadata-over-limit.sog"),
&metadata, &error));
CHECK(HasCode(error, gssog::diag::kImportLimitExceeded));
CHECK(error.find("meta.json is 4194305 bytes") != std::string::npos);
error.clear();
CHECK(!gssog::SogReader().ReadMetadata(Fixture("too-many-entries.sog"),
&metadata, &error));
CHECK(HasCode(error, gssog::diag::kImportLimitExceeded));
Expand Down
12 changes: 10 additions & 2 deletions plugins/gaussian-sog/tools/generate_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -664,8 +664,16 @@ def main() -> None:
# from the hostile value.
MIB = 1024 * 1024

# One entry past the 64-entry ZIP budget.
padding = {f"pad-{index:02d}.bin": b"" for index in range(65 - 1 - len(one_planes))}
# The metadata limit applies to the size after inflation.
padded_meta = meta_bytes(one_meta).ljust(4 * MIB, b" ")
write_bundle("zip-metadata-at-limit.sog", padded_meta, one_planes, compress=True)
write_bundle("zip-metadata-over-limit.sog", one_meta, one_planes,
declared_sizes={"meta.json": 4 * MIB + 1})

# Exactly at and one entry past the 64-entry ZIP budget.
padding = {f"pad-{index:02d}.bin": b"" for index in range(64 - 1 - len(one_planes))}
write_bundle("zip-entry-count-at-limit.sog", one_meta, one_planes, extra=padding)
padding[f"pad-{len(padding):02d}.bin"] = b""
write_bundle("too-many-entries.sog", one_meta, one_planes, extra=padding)

# A single entry declaring more than the 512 MiB per-entry bound.
Expand Down
Loading