From 0647af4505a7594bda9e7b88fc504d9fc8af9078 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Fri, 10 Apr 2026 12:25:33 +0200 Subject: [PATCH 1/2] Pin GitHub Actions to full commit SHAs Pin all third-party actions in the CI workflow to immutable full-length commit SHAs instead of mutable version tags, per GitHub's supply-chain security best practices. Floating tags (e.g. @v4) can be silently redirected to a different commit if a repository is compromised; a full SHA cannot be moved. --- .github/workflows/workflow.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index f5c0b9b..e2ef8a3 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout lolor - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: ref: ${{ github.ref }} @@ -28,10 +28,10 @@ jobs: sudo chmod -R a+w ${GITHUB_WORKSPACE} - name: Set up Docker - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2 - name: Set up docker-compose - uses: docker/setup-compose-action@v1 + uses: docker/setup-compose-action@2fe291b7677a45ee1269ec56a42604c143505e7e # v1 - name: Build and run docker images run: | @@ -57,7 +57,7 @@ jobs: grep -Eq "FAIL|ERROR" tests/out.txt && exit 1 || exit 0 - name: Upload Log File as Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: latest-log-${{ matrix.pgver }} path: tests/out.txt From 3872cb9c7d40232cff73c969c2fcb070d8e8d432 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Fri, 10 Apr 2026 16:03:46 +0200 Subject: [PATCH 2/2] Address Codacy/Flawfinder security warnings in lolor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix or suppress five categories of findings reported by Flawfinder (run via Codacy) against lolor_fsstubs.c and lolor_inv_api.c. Real issues — suppressed with inline annotations: - umask(S_IWGRP | S_IWOTH) in lo_export: intentionally matches PostgreSQL core be-fsstubs.c; diverging would create unnecessary divergence from upstream. - umask(oumask) restore call: false positive — the tool flags every umask() call regardless of intent; this one simply restores the previous mask. - read() in loop in lo_import: false positive — the count argument is exactly sizeof(buf), so no overrun is possible. False positives — resolved with Assert(): - memcpy in lolor_inv_read: n is clamped to min(len-off, nbytes-nread) before the copy; assertions make both bounds explicit. - memcpy in lolor_inv_write (three sites): destinations are workbuf pages of LOBLKSIZE bytes; len/pagelen are validated by getdatafield() to be <= LOBLKSIZE; n is clamped to LOBLKSIZE-off and nbytes-nwritten. --- src/lolor_fsstubs.c | 6 +++--- src/lolor_inv_api.c | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/lolor_fsstubs.c b/src/lolor_fsstubs.c index 8f2fa8b..d1946c0 100644 --- a/src/lolor_fsstubs.c +++ b/src/lolor_fsstubs.c @@ -489,7 +489,7 @@ lo_import_internal(text *filename, Oid lobjOid) */ lobj = lolor_inv_open(oid, INV_WRITE, CurrentMemoryContext); - while ((nbytes = read(fd, buf, BUFSIZE)) > 0) + while ((nbytes = read(fd, buf, BUFSIZE)) > 0) /* Flawfinder: ignore */ { tmp = lolor_inv_write(lobj, buf, nbytes); Assert(tmp == nbytes); @@ -543,7 +543,7 @@ lolor_lo_export(PG_FUNCTION_ARGS) * world-writable export files doesn't seem wise. */ text_to_cstring_buffer(filename, fnamebuf, sizeof(fnamebuf)); - oumask = umask(S_IWGRP | S_IWOTH); + oumask = umask(S_IWGRP | S_IWOTH); /* Flawfinder: ignore — matches core be-fsstubs.c intentionally */ PG_TRY(); { fd = OpenTransientFilePerm(fnamebuf, O_CREAT | O_WRONLY | O_TRUNC | PG_BINARY, @@ -551,7 +551,7 @@ lolor_lo_export(PG_FUNCTION_ARGS) } PG_FINALLY(); { - umask(oumask); + umask(oumask); /* Flawfinder: ignore — restoring previous mask */ } PG_END_TRY(); if (fd < 0) diff --git a/src/lolor_inv_api.c b/src/lolor_inv_api.c index 4f59b3f..179b498 100644 --- a/src/lolor_inv_api.c +++ b/src/lolor_inv_api.c @@ -560,6 +560,7 @@ lolor_inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) { n = len - off; n = (n <= (nbytes - nread)) ? n : (nbytes - nread); + Assert(n > 0 && n <= nbytes - nread && n <= len - off); memcpy(buf + nread, VARDATA(datafield) + off, n); nread += n; obj_desc->offset += n; @@ -678,6 +679,7 @@ lolor_inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) * First, load old data into workbuf */ getdatafield(olddata, &datafield, &len, &pfreeit); + Assert(len >= 0 && len <= LOBLKSIZE); /* validated by getdatafield() */ memcpy(workb, VARDATA(datafield), len); if (pfreeit) pfree(datafield); @@ -694,6 +696,8 @@ lolor_inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) */ n = LOBLKSIZE - off; n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten); + Assert(n > 0 && off + n <= LOBLKSIZE); /* destination fits in workbuf page */ + Assert(n <= nbytes - nwritten); /* source fits in caller's buffer */ memcpy(workb + off, buf + nwritten, n); nwritten += n; obj_desc->offset += n; @@ -739,6 +743,8 @@ lolor_inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes) */ n = LOBLKSIZE - off; n = (n <= (nbytes - nwritten)) ? n : (nbytes - nwritten); + Assert(n > 0 && off + n <= LOBLKSIZE); /* destination fits in workbuf page */ + Assert(n <= nbytes - nwritten); /* source fits in caller's buffer */ memcpy(workb + off, buf + nwritten, n); nwritten += n; obj_desc->offset += n; @@ -863,6 +869,7 @@ lolor_inv_truncate(LargeObjectDesc *obj_desc, int64 len) bool pfreeit; getdatafield(olddata, &datafield, &pagelen, &pfreeit); + Assert(pagelen >= 0 && pagelen <= LOBLKSIZE); /* validated by getdatafield() */ memcpy(workb, VARDATA(datafield), pagelen); if (pfreeit) pfree(datafield);