-
Notifications
You must be signed in to change notification settings - Fork 15k
/
lib_src_switch_buffer_kmaxlength_to_size_t.patch
234 lines (209 loc) · 8.08 KB
/
lib_src_switch_buffer_kmaxlength_to_size_t.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ben Noordhuis <info@bnoordhuis.nl>
Date: Sat, 18 Jan 2020 10:55:31 +0100
Subject: lib,src: switch Buffer::kMaxLength to size_t
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Change the type of `Buffer::kMaxLength` to size_t because upcoming
changes in V8 will allow typed arrays > 2 GB on 64 bits platforms.
Not all platforms handle file reads and writes > 2 GB though so keep
enforcing the 2 GB typed array limit for I/O operations.
Fixes: https://github.com/nodejs/node/issues/31399
Refs: https://github.com/libuv/libuv/pull/1501
PR-URL: https://github.com/nodejs/node/pull/31406
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Shelley Vohr <codebytere@gmail.com>
diff --git a/lib/fs.js b/lib/fs.js
index 9b70b237ef00e19983b39902b50233c682492771..7e1cb0e9e72078340e1f2cc77cd70e7a1f6bf595 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -24,6 +24,10 @@
'use strict';
+// Most platforms don't allow reads or writes >= 2 GB.
+// See https://github.com/libuv/libuv/pull/1501.
+const kIoMaxLength = 2 ** 31 - 1;
+
const {
Map,
MathMax,
@@ -53,7 +57,7 @@ const {
const pathModule = require('path');
const { isArrayBufferView } = require('internal/util/types');
const binding = internalBinding('fs');
-const { Buffer, kMaxLength } = require('buffer');
+const { Buffer } = require('buffer');
const {
codes: {
ERR_FS_FILE_TOO_LARGE,
@@ -278,7 +282,7 @@ function readFileAfterStat(err, stats) {
const size = context.size = isFileType(stats, S_IFREG) ? stats[8] : 0;
- if (size > kMaxLength) {
+ if (size > kIoMaxLength) {
err = new ERR_FS_FILE_TOO_LARGE(size);
return context.close(err);
}
@@ -335,7 +339,7 @@ function tryCreateBuffer(size, fd, isUserFd) {
let threw = true;
let buffer;
try {
- if (size > kMaxLength) {
+ if (size > kIoMaxLength) {
throw new ERR_FS_FILE_TOO_LARGE(size);
}
buffer = Buffer.allocUnsafe(size);
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index a3d99a79c6340c3bc2955bf3b36d11e8676d1aa1..4e2d1e48257acff20131ee998a0774b709d5dbcc 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -827,9 +827,7 @@ E('ERR_FALSY_VALUE_REJECTION', function(reason) {
this.reason = reason;
return 'Promise was rejected with falsy value';
}, Error);
-E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than possible Buffer: ' +
- `${kMaxLength} bytes`,
- RangeError);
+E('ERR_FS_FILE_TOO_LARGE', 'File size (%s) is greater than 2 GB', RangeError);
E('ERR_FS_INVALID_SYMLINK_TYPE',
'Symlink type must be one of "dir", "file", or "junction". Received "%s"',
Error); // Switch to TypeError. The current implementation does not seem right
diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js
index 31eaeef28462166036c5a71a474e1b3c018cfa53..91cf9f6be52d47ba7353ca19f687ab2bb41cbd22 100644
--- a/lib/internal/fs/promises.js
+++ b/lib/internal/fs/promises.js
@@ -1,5 +1,9 @@
'use strict';
+// Most platforms don't allow reads or writes >= 2 GB.
+// See https://github.com/libuv/libuv/pull/1501.
+const kIoMaxLength = 2 ** 31 - 1;
+
const {
MathMax,
MathMin,
@@ -15,7 +19,7 @@ const {
S_IFREG
} = internalBinding('constants').fs;
const binding = internalBinding('fs');
-const { Buffer, kMaxLength } = require('buffer');
+const { Buffer } = require('buffer');
const {
ERR_FS_FILE_TOO_LARGE,
ERR_INVALID_ARG_TYPE,
@@ -166,7 +170,7 @@ async function readFileHandle(filehandle, options) {
size = 0;
}
- if (size > kMaxLength)
+ if (size > kIoMaxLength)
throw new ERR_FS_FILE_TOO_LARGE(size);
const chunks = [];
diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js
index ed4e9bb66ad79ffd542b769ab17a28bb801764c6..84f9e3b806a237c599f85dcb8fb93bfe9a098eda 100644
--- a/lib/internal/fs/utils.js
+++ b/lib/internal/fs/utils.js
@@ -12,7 +12,7 @@ const {
Symbol,
} = primordials;
-const { Buffer, kMaxLength } = require('buffer');
+const { Buffer } = require('buffer');
const {
codes: {
ERR_FS_INVALID_SYMLINK_TYPE,
@@ -72,6 +72,10 @@ const {
const isWindows = process.platform === 'win32';
+// Most platforms don't allow reads or writes >= 2 GB.
+// See https://github.com/libuv/libuv/pull/1501.
+const kIoMaxLength = 2 ** 31 - 1;
+
let fs;
function lazyLoadFs() {
if (!fs) {
@@ -569,7 +573,7 @@ const validateOffsetLengthWrite = hideStackFrames(
throw new ERR_OUT_OF_RANGE('offset', `<= ${byteLength}`, offset);
}
- const max = byteLength > kMaxLength ? kMaxLength : byteLength;
+ const max = byteLength > kIoMaxLength ? kIoMaxLength : byteLength;
if (length > max - offset) {
throw new ERR_OUT_OF_RANGE('length', `<= ${max - offset}`, length);
}
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
index 59baa45413d500272d0e293ab06bfe4d24e5e0cb..4d1951b740240bff231b7f4c855beb5b73d076af 100644
--- a/src/node_buffer.cc
+++ b/src/node_buffer.cc
@@ -62,6 +62,7 @@ using v8::Local;
using v8::Maybe;
using v8::MaybeLocal;
using v8::Nothing;
+using v8::Number;
using v8::Object;
using v8::String;
using v8::Uint32;
@@ -1161,7 +1162,7 @@ void Initialize(Local<Object> target,
target->Set(env->context(),
FIXED_ONE_BYTE_STRING(env->isolate(), "kMaxLength"),
- Integer::NewFromUnsigned(env->isolate(), kMaxLength)).Check();
+ Number::New(env->isolate(), kMaxLength)).Check();
target->Set(env->context(),
FIXED_ONE_BYTE_STRING(env->isolate(), "kStringMaxLength"),
diff --git a/src/node_buffer.h b/src/node_buffer.h
index 11010017ce0df8367b1992bd9df57117ff50454d..606a6f5caa3b11b6d2a9068ed2fd65800530a5eb 100644
--- a/src/node_buffer.h
+++ b/src/node_buffer.h
@@ -29,7 +29,7 @@ namespace node {
namespace Buffer {
-static const unsigned int kMaxLength = v8::TypedArray::kMaxLength;
+static const size_t kMaxLength = v8::TypedArray::kMaxLength;
typedef void (*FreeCallback)(char* data, void* hint);
diff --git a/test/parallel/test-fs-util-validateoffsetlengthwrite.js b/test/parallel/test-fs-util-validateoffsetlengthwrite.js
index be6d8acea77efa5adc82a6bcaaa192167b510fb0..e2c583749d041d76da630bbbf6b46ac490076c56 100644
--- a/test/parallel/test-fs-util-validateoffsetlengthwrite.js
+++ b/test/parallel/test-fs-util-validateoffsetlengthwrite.js
@@ -4,7 +4,10 @@
require('../common');
const assert = require('assert');
const { validateOffsetLengthWrite } = require('internal/fs/utils');
-const { kMaxLength } = require('buffer');
+
+// Most platforms don't allow reads or writes >= 2 GB.
+// See https://github.com/libuv/libuv/pull/1501.
+const kIoMaxLength = 2 ** 31 - 1;
// RangeError when offset > byteLength
{
@@ -22,27 +25,27 @@ const { kMaxLength } = require('buffer');
);
}
-// RangeError when byteLength > kMaxLength, and length > kMaxLength - offset .
+// RangeError when byteLength > kIoMaxLength, and length > kIoMaxLength - offset .
{
- const offset = kMaxLength;
+ const offset = kIoMaxLength;
const length = 100;
- const byteLength = kMaxLength + 1;
+ const byteLength = kIoMaxLength + 1;
assert.throws(
() => validateOffsetLengthWrite(offset, length, byteLength),
{
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError',
message: 'The value of "length" is out of range. ' +
- `It must be <= ${kMaxLength - offset}. Received ${length}`
+ `It must be <= ${kIoMaxLength - offset}. Received ${length}`
}
);
}
-// RangeError when byteLength < kMaxLength, and length > byteLength - offset .
+// RangeError when byteLength < kIoMaxLength, and length > byteLength - offset.
{
- const offset = kMaxLength - 150;
+ const offset = kIoMaxLength - 150;
const length = 200;
- const byteLength = kMaxLength - 100;
+ const byteLength = kIoMaxLength - 100;
assert.throws(
() => validateOffsetLengthWrite(offset, length, byteLength),
{