From beab331b9b161e436211cc1d9449e50d30faafd6 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Mon, 5 Oct 2026 17:36:39 +0200 Subject: [PATCH 1/2] Fix macOS extraction tests and Android SDK setup --- .github/workflows/release.yml | 2 ++ .github/workflows/snapshot.yml | 2 ++ .../NativeLibraryExtractionTest.java | 31 ++++++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3309f28..5ba938f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,6 +56,8 @@ jobs: - name: Setup Android SDK if: matrix.module == 'saferalloc-natives-android' uses: android-actions/setup-android@v3 + with: + packages: platform-tools - name: Install Android NDK if: matrix.module == 'saferalloc-natives-android' diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 09ca6f2..90d28a0 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -50,6 +50,8 @@ jobs: - name: Setup Android SDK if: matrix.module == 'saferalloc-natives-android' uses: android-actions/setup-android@v3 + with: + packages: platform-tools - name: Install Android NDK if: matrix.module == 'saferalloc-natives-android' diff --git a/saferalloc/src/test/java/org/ngengine/saferalloc/NativeLibraryExtractionTest.java b/saferalloc/src/test/java/org/ngengine/saferalloc/NativeLibraryExtractionTest.java index 40563e7..40b1025 100644 --- a/saferalloc/src/test/java/org/ngengine/saferalloc/NativeLibraryExtractionTest.java +++ b/saferalloc/src/test/java/org/ngengine/saferalloc/NativeLibraryExtractionTest.java @@ -3,8 +3,12 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.Comparator; import java.util.Set; +import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -57,14 +61,33 @@ void neverFollowsAPoisonedNativeSymlink() throws IOException { @Test void rejectsReplaceableParent() throws IOException { if (!Files.getFileStore(root).supportsFileAttributeView("posix")) return; - Path replaceable = Files.createTempDirectory("saferalloc-unsafe-"); + // macOS java.io.tmpdir is below a private user directory, so use shared /tmp. + Path replaceable = Files.createTempDirectory(Paths.get("/tmp"), "saferalloc-unsafe-"); try { Files.setPosixFilePermissions(replaceable, - java.nio.file.attribute.PosixFilePermissions.fromString("rwxrwxrwx")); - assertThrows(IOException.class, () -> + PosixFilePermissions.fromString("rwxrwxrwx")); + IOException failure = assertThrows(IOException.class, () -> NativeLibraryExtraction.createDirectory(replaceable, "saferalloc-")); + assertTrue(failure.getMessage().startsWith("Native extraction ancestor is writable by other users:")); } finally { - Files.deleteIfExists(replaceable); + // Preserve the assertion failure even if a regression creates a child directory. + try (Stream paths = Files.walk(replaceable)) { + for (Path path : paths.sorted(Comparator.reverseOrder()).toArray(Path[]::new)) { + Files.deleteIfExists(path); + } + } } } + + @Test + void acceptsWritableParentInsidePrivateAncestor() throws IOException { + if (!Files.getFileStore(root).supportsFileAttributeView("posix")) return; + Files.setPosixFilePermissions(root, PosixFilePermissions.fromString("rwx------")); + Path protectedParent = Files.createDirectory(root.resolve("writable")); + Files.setPosixFilePermissions(protectedParent, PosixFilePermissions.fromString("rwxrwxrwx")); + + Path directory = NativeLibraryExtraction.createDirectory(protectedParent, "saferalloc-"); + assertEquals(protectedParent.toRealPath(), directory.getParent()); + assertEquals(PosixFilePermissions.fromString("rwx------"), Files.getPosixFilePermissions(directory)); + } } From 4f68c5e90b1eb8b7510eac748011271a9ddaa51d Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Mon, 5 Oct 2026 17:38:26 +0200 Subject: [PATCH 2/2] Verify snapshot publications without credentials on pull requests --- .github/workflows/snapshot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 90d28a0..5f337d6 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -81,6 +81,7 @@ jobs: - name: Publish snapshot to Maven Central snapshots + if: github.event_name == 'push' && github.repository == 'NostrGameEngine/saferalloc' shell: bash env: ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} @@ -90,6 +91,12 @@ jobs: run: | ./gradlew --no-daemon -PVERSION_NAME=${VERSION} :${{ matrix.module }}:publishToSonatype + - name: Verify native publication locally + if: github.event_name != 'push' || github.repository != 'NostrGameEngine/saferalloc' + shell: bash + run: | + ./gradlew --no-daemon -PVERSION_NAME=${VERSION} :${{ matrix.module }}:publishToMavenLocal + publish-core: runs-on: ubuntu-latest steps: @@ -120,6 +127,7 @@ jobs: echo "VERSION=${VERSION}" >> "$GITHUB_ENV" - name: Publish core snapshot + if: github.event_name == 'push' && github.repository == 'NostrGameEngine/saferalloc' shell: bash env: ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} @@ -128,3 +136,9 @@ jobs: ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_PASSPHRASE }} run: | ./gradlew --no-daemon -PVERSION_NAME=${VERSION} :saferalloc:publishToSonatype + + - name: Verify core publication locally + if: github.event_name != 'push' || github.repository != 'NostrGameEngine/saferalloc' + shell: bash + run: | + ./gradlew --no-daemon -PVERSION_NAME=${VERSION} :saferalloc:publishToMavenLocal