fs: use signed types for stat data · nodejs/node@100f6de · GitHub
Skip to content

Commit 100f6de

Browse files
LiviaMedeirosdanielleadams
authored andcommitted
fs: use signed types for stat data
This allows to support timestamps before 1970-01-01. On Windows, it's not supported due to Y2038 issue. PR-URL: #43714 Fixes: #43707 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent e89e0b4 commit 100f6de

5 files changed

Lines changed: 105 additions & 14 deletions

File tree

lib/internal/fs/utils.js

Lines changed: 10 additions & 7 deletions

src/aliased_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ typedef AliasedBufferBase<int32_t, v8::Int32Array> AliasedInt32Array;
307307
typedef AliasedBufferBase<uint8_t, v8::Uint8Array> AliasedUint8Array;
308308
typedef AliasedBufferBase<uint32_t, v8::Uint32Array> AliasedUint32Array;
309309
typedef AliasedBufferBase<double, v8::Float64Array> AliasedFloat64Array;
310-
typedef AliasedBufferBase<uint64_t, v8::BigUint64Array> AliasedBigUint64Array;
310+
typedef AliasedBufferBase<int64_t, v8::BigInt64Array> AliasedBigInt64Array;
311311
} // namespace node
312312

313313
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

src/node_file-inl.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,22 @@ template <typename NativeT, typename V8T>
8686
void FillStatsArray(AliasedBufferBase<NativeT, V8T>* fields,
8787
const uv_stat_t* s,
8888
const size_t offset) {
89-
#define SET_FIELD_WITH_STAT(stat_offset, stat) \
90-
fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \
89+
#define SET_FIELD_WITH_STAT(stat_offset, stat) \
90+
fields->SetValue(offset + static_cast<size_t>(FsStatsOffset::stat_offset), \
9191
static_cast<NativeT>(stat))
9292

93-
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \
94-
/* NOLINTNEXTLINE(runtime/int) */ \
93+
// On win32, time is stored in uint64_t and starts from 1601-01-01.
94+
// libuv calculates tv_sec and tv_nsec from it and converts to signed long,
95+
// which causes Y2038 overflow. On the other platforms it is safe to treat
96+
// negative values as pre-epoch time.
97+
#ifdef _WIN32
98+
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \
99+
/* NOLINTNEXTLINE(runtime/int) */ \
95100
SET_FIELD_WITH_STAT(stat_offset, static_cast<unsigned long>(stat))
101+
#else
102+
#define SET_FIELD_WITH_TIME_STAT(stat_offset, stat) \
103+
SET_FIELD_WITH_STAT(stat_offset, static_cast<double>(stat))
104+
#endif // _WIN32
96105

97106
SET_FIELD_WITH_STAT(kDev, s->st_dev);
98107
SET_FIELD_WITH_STAT(kMode, s->st_mode);
@@ -233,7 +242,7 @@ FSReqBase* GetReqWrap(const v8::FunctionCallbackInfo<v8::Value>& args,
233242
Environment* env = binding_data->env();
234243
if (value->StrictEquals(env->fs_use_promises_symbol())) {
235244
if (use_bigint) {
236-
return FSReqPromise<AliasedBigUint64Array>::New(binding_data, use_bigint);
245+
return FSReqPromise<AliasedBigInt64Array>::New(binding_data, use_bigint);
237246
} else {
238247
return FSReqPromise<AliasedFloat64Array>::New(binding_data, use_bigint);
239248
}

src/node_file.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class BindingData : public SnapshotableObject {
1818
explicit BindingData(Environment* env, v8::Local<v8::Object> wrap);
1919

2020
AliasedFloat64Array stats_field_array;
21-
AliasedBigUint64Array stats_field_bigint_array;
21+
AliasedBigInt64Array stats_field_bigint_array;
2222

2323
std::vector<BaseObjectPtr<FileHandleReadWrap>>
2424
file_handle_read_wrap_freelist;
Lines changed: 79 additions & 0 deletions

0 commit comments

Comments
 (0)