Repository navigation
fs.statSync, fs.stat and fs.promises.stat returns 'Invalid Date' for atime/ctime/mtime with negative epoch time #43707
Description
Activity
@nodejs/fs
- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.fsIssues and PRs related to file-system APIs and the fs module.Issues and PRs related to file-system APIs and the fs module.
on Jul 7, 2022 It's a signed-to-unsigned conversion bug:
$ touch -t 196912312359.59 x && node -p 'fs.statSync("x", {bigint: true})' | grep Ns atimeNs: 18446744073709548015000000000n, mtimeNs: 18446744073709548015000000000n, ctimeNs: 1657177398636601096n, birthtimeNs: 1657177398636510656n,Internally, the stats are handed off from C++ to JS in a BigUint64Array but that makes negative values wrap around. The fix is to use a BigInt64Array instead. Pull request welcome.
edit: in particular, it's this (insidiously misnamed) field:
Line 21 in 7d13f5e
AliasedBigUint64Array stats_field_bigint_array;
And here is where it's converted to a stats object:
Lines 534 to 545 in 7d13f5e
if (isBigUint64Array(stats)) { return new BigIntStats( stats[0 + offset], stats[1 + offset], stats[2 + offset], stats[3 + offset], stats[4 + offset], stats[5 + offset], stats[6 + offset], stats[7 + offset], stats[8 + offset], stats[9 + offset], nsFromTimeSpecBigInt(stats[10 + offset], stats[11 + offset]), nsFromTimeSpecBigInt(stats[12 + offset], stats[13 + offset]), nsFromTimeSpecBigInt(stats[14 + offset], stats[15 + offset]), nsFromTimeSpecBigInt(stats[16 + offset], stats[17 + offset]) ); } Non-bigint stats are returned as
Float64Arrayso perhaps this requires adjustingunsigned long longs (or what it's aliased to) in C++ bindings as well.Sorry yes, I forgot to mention that. That logic is here:
Lines 93 to 95 in 7d13f5e
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \ /* NOLINTNEXTLINE(runtime/int) */ \ SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat)) - added a commit that references this issue
on Jul 18, 2022 Note: on Windows platform, there still is an overflow on negative dates, to postpone Y2038 overflow.
It shouldn't lead toInvalid Date, and right now is unavoidable without breaking underlying ABI.- added a commit that references this issue
on Jul 26, 2022 - added a commit that references this issue
on Sep 5, 2022
Version
v16.15.1
Platform
Linux localhost.localdomain 4.18.0-394.el8.x86_64 #1 SMP Tue May 31 16:19:11 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Subsystem
File system
What steps will reproduce the bug?
fs.statSyncandfs.promises.statfor file hogehoge.How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior?
ctime/mtime/atime with negative epoch time shall be treated as it is.
In other words, if -1 then it shall be 1 second before epoch.
Actually,
Date()supports negative epoch time.As
stat(2)supports negative epoch time, which can be observed via ls command, I don't see whyfs.stat/fs.statSync/fs.promises.stattreats negative epoch asNaN.What do you see instead?
Additional information
No response