From f403537a3489f5e3007f8489cd38c7b4f02af324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20G=C3=BCzel?= Date: Fri, 6 Nov 2026 18:23:48 +0300 Subject: [PATCH] src: check mtime seconds for file-backed blobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compare the seconds part of mtime as well as nanoseconds. otherwise, same-size edits can go unnoticed on filesystems with coarse timestamps. add regression coverage for both file-backed blob apis. Fixes: https://github.com/nodejs/node/issues/67283 Signed-off-by: Fatih Güzel --- src/dataqueue/queue.cc | 1 + test/parallel/test-blob-file-backed-mtime.js | 36 ++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 test/parallel/test-blob-file-backed-mtime.js diff --git a/src/dataqueue/queue.cc b/src/dataqueue/queue.cc index 96a7956b8749..30df8bdf71f6 100644 --- a/src/dataqueue/queue.cc +++ b/src/dataqueue/queue.cc @@ -936,6 +936,7 @@ class FdEntry final : public EntryImpl { bool is_modified(const uv_stat_t& other) { return other.st_size != stat_.st_size || + other.st_mtim.tv_sec != stat_.st_mtim.tv_sec || other.st_mtim.tv_nsec != stat_.st_mtim.tv_nsec; } diff --git a/test/parallel/test-blob-file-backed-mtime.js b/test/parallel/test-blob-file-backed-mtime.js new file mode 100644 index 000000000000..1fb12e890382 --- /dev/null +++ b/test/parallel/test-blob-file-backed-mtime.js @@ -0,0 +1,36 @@ +'use strict'; + +require('../common'); +const assert = require('node:assert'); +const { test } = require('node:test'); +const { + openAsBlob, + openAsBlobSync, + statSync, + utimesSync, + writeFileSync, +} = require('node:fs'); +const tmpdir = require('../common/tmpdir'); + +tmpdir.refresh(); + +for (const openBlob of [openAsBlob, openAsBlobSync]) { + test(`${openBlob.name} detects whole-second mtime changes`, async () => { + const file = tmpdir.resolve(openBlob.name); + const time = 1_700_000_000; + writeFileSync(file, 'before'); + utimesSync(file, time, time); + const before = statSync(file, { bigint: true }); + + const blob = await openBlob(file); + assert.strictEqual(await blob.text(), 'before'); + + writeFileSync(file, 'after!'); + utimesSync(file, time, time + 2); + const after = statSync(file, { bigint: true }); + assert.strictEqual(after.size, before.size); + assert.strictEqual(after.mtimeNs - before.mtimeNs, 2_000_000_000n); + + await assert.rejects(blob.text(), { name: 'NotReadableError' }); + }); +}