Skip to content

Commit 93eb9c0

Browse files
targosnodejs-github-bot
authored andcommitted
[HACK] temporary FastApiTypedArray fixes
1 parent d2eca27 commit 93eb9c0

File tree

4 files changed

+44
-202
lines changed

4 files changed

+44
-202
lines changed

src/crypto/crypto_timing.cc

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
namespace node {
1212

1313
using v8::FastApiCallbackOptions;
14-
using v8::FastApiTypedArray;
1514
using v8::FunctionCallbackInfo;
1615
using v8::HandleScope;
1716
using v8::Local;
@@ -50,35 +49,11 @@ void TimingSafeEqual(const FunctionCallbackInfo<Value>& args) {
5049
CRYPTO_memcmp(buf1.data(), buf2.data(), buf1.size()) == 0);
5150
}
5251

53-
bool FastTimingSafeEqual(Local<Value> receiver,
54-
const FastApiTypedArray<uint8_t>& a,
55-
const FastApiTypedArray<uint8_t>& b,
56-
// NOLINTNEXTLINE(runtime/references)
57-
FastApiCallbackOptions& options) {
58-
uint8_t* data_a;
59-
uint8_t* data_b;
60-
if (a.length() != b.length() || !a.getStorageIfAligned(&data_a) ||
61-
!b.getStorageIfAligned(&data_b)) {
62-
TRACK_V8_FAST_API_CALL("crypto.timingSafeEqual.error");
63-
HandleScope scope(options.isolate);
64-
THROW_ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH(options.isolate);
65-
return false;
66-
}
67-
68-
TRACK_V8_FAST_API_CALL("crypto.timingSafeEqual.ok");
69-
return CRYPTO_memcmp(data_a, data_b, a.length()) == 0;
70-
}
71-
72-
static v8::CFunction fast_equal(v8::CFunction::Make(FastTimingSafeEqual));
73-
7452
void Initialize(Environment* env, Local<Object> target) {
75-
SetFastMethodNoSideEffect(
76-
env->context(), target, "timingSafeEqual", TimingSafeEqual, &fast_equal);
53+
SetMethod(env->context(), target, "timingSafeEqual", TimingSafeEqual);
7754
}
7855
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
7956
registry->Register(TimingSafeEqual);
80-
registry->Register(FastTimingSafeEqual);
81-
registry->Register(fast_equal.GetTypeInfo());
8257
}
8358
} // namespace Timing
8459

src/node_buffer.cc

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,15 @@
4242
#include "nbytes.h"
4343

4444
#define THROW_AND_RETURN_UNLESS_BUFFER(env, obj) \
45-
THROW_AND_RETURN_IF_NOT_BUFFER(env, obj, "argument") \
45+
THROW_AND_RETURN_IF_NOT_BUFFER(env, obj, "argument")
46+
47+
#define THROW_AND_RETURN_VAL_UNLESS_BUFFER(isolate, val, prefix, retval) \
48+
do { \
49+
if (!Buffer::HasInstance(val)) { \
50+
node::THROW_ERR_INVALID_ARG_TYPE(isolate, prefix " must be a buffer"); \
51+
return retval; \
52+
} \
53+
} while (0)
4654

4755
#define THROW_AND_RETURN_IF_OOB(r) \
4856
do { \
@@ -61,7 +69,6 @@ using v8::BackingStore;
6169
using v8::BackingStoreInitializationMode;
6270
using v8::Context;
6371
using v8::EscapableHandleScope;
64-
using v8::FastApiTypedArray;
6572
using v8::FunctionCallbackInfo;
6673
using v8::Global;
6774
using v8::HandleScope;
@@ -578,19 +585,17 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
578585

579586
// Assume caller has properly validated args.
580587
uint32_t FastCopy(Local<Value> receiver,
581-
const v8::FastApiTypedArray<uint8_t>& source,
582-
const v8::FastApiTypedArray<uint8_t>& target,
588+
Local<Value> source_obj,
589+
Local<Value> target_obj,
583590
uint32_t target_start,
584591
uint32_t source_start,
585-
uint32_t to_copy) {
586-
uint8_t* source_data;
587-
CHECK(source.getStorageIfAligned(&source_data));
588-
589-
uint8_t* target_data;
590-
CHECK(target.getStorageIfAligned(&target_data));
591-
592-
memmove(target_data + target_start, source_data + source_start, to_copy);
592+
uint32_t to_copy,
593+
// NOLINTNEXTLINE(runtime/references) This is V8 api.
594+
v8::FastApiCallbackOptions& options) {
595+
ArrayBufferViewContents<char> source(source_obj);
596+
SPREAD_BUFFER_ARG(target_obj, target);
593597

598+
memmove(target_data + target_start, source.data() + source_start, to_copy);
594599
return to_copy;
595600
}
596601

@@ -853,24 +858,6 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
853858
args.GetReturnValue().Set(val);
854859
}
855860

856-
int32_t FastCompare(v8::Local<v8::Value>,
857-
const FastApiTypedArray<uint8_t>& a,
858-
const FastApiTypedArray<uint8_t>& b) {
859-
uint8_t* data_a;
860-
uint8_t* data_b;
861-
CHECK(a.getStorageIfAligned(&data_a));
862-
CHECK(b.getStorageIfAligned(&data_b));
863-
864-
size_t cmp_length = std::min(a.length(), b.length());
865-
866-
return normalizeCompareVal(
867-
cmp_length > 0 ? memcmp(data_a, data_b, cmp_length) : 0,
868-
a.length(),
869-
b.length());
870-
}
871-
872-
static v8::CFunction fast_compare(v8::CFunction::Make(FastCompare));
873-
874861
// Computes the offset for starting an indexOf or lastIndexOf search.
875862
// Returns either a valid offset in [0...<length - 1>], ie inside the Buffer,
876863
// or -1 to signal that there is no possible match.
@@ -1121,7 +1108,7 @@ int32_t IndexOfNumber(const uint8_t* buffer_data,
11211108
return ptr != nullptr ? static_cast<int32_t>(ptr_uint8 - buffer_data) : -1;
11221109
}
11231110

1124-
void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
1111+
void IndexOfNumber(const FunctionCallbackInfo<Value>& args) {
11251112
CHECK(args[1]->IsUint32());
11261113
CHECK(args[2]->IsNumber());
11271114
CHECK(args[3]->IsBoolean());
@@ -1137,20 +1124,6 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
11371124
buffer.data(), buffer.length(), needle, offset_i64, is_forward));
11381125
}
11391126

1140-
int32_t FastIndexOfNumber(v8::Local<v8::Value>,
1141-
const FastApiTypedArray<uint8_t>& buffer,
1142-
uint32_t needle,
1143-
int64_t offset_i64,
1144-
bool is_forward) {
1145-
uint8_t* buffer_data;
1146-
CHECK(buffer.getStorageIfAligned(&buffer_data));
1147-
return IndexOfNumber(
1148-
buffer_data, buffer.length(), needle, offset_i64, is_forward);
1149-
}
1150-
1151-
static v8::CFunction fast_index_of_number(
1152-
v8::CFunction::Make(FastIndexOfNumber));
1153-
11541127
void Swap16(const FunctionCallbackInfo<Value>& args) {
11551128
Environment* env = Environment::GetCurrent(args);
11561129
THROW_AND_RETURN_UNLESS_BUFFER(env, args[0]);
@@ -1498,21 +1471,25 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
14981471

14991472
template <encoding encoding>
15001473
uint32_t FastWriteString(Local<Value> receiver,
1501-
const v8::FastApiTypedArray<uint8_t>& dst,
1474+
Local<Value> dst,
15021475
const v8::FastOneByteString& src,
15031476
uint32_t offset,
1504-
uint32_t max_length) {
1505-
uint8_t* dst_data;
1506-
CHECK(dst.getStorageIfAligned(&dst_data));
1507-
CHECK(offset <= dst.length());
1508-
CHECK(dst.length() - offset <= std::numeric_limits<uint32_t>::max());
1477+
uint32_t max_length,
1478+
// NOLINTNEXTLINE(runtime/references) This is V8 api.
1479+
v8::FastApiCallbackOptions& options) {
1480+
THROW_AND_RETURN_VAL_UNLESS_BUFFER(options.isolate, dst, "dst", 0);
1481+
SPREAD_BUFFER_ARG(dst, dst_buffer);
1482+
CHECK(dst_buffer_length <=
1483+
static_cast<size_t>(std::numeric_limits<uint32_t>::max()));
1484+
uint32_t dst_size = static_cast<uint32_t>(dst_buffer_length);
1485+
CHECK(offset <= dst_size);
15091486
TRACK_V8_FAST_API_CALL("buffer.writeString");
15101487

15111488
return WriteOneByteString<encoding>(
15121489
src.data,
15131490
src.length,
1514-
reinterpret_cast<char*>(dst_data + offset),
1515-
std::min<uint32_t>(dst.length() - offset, max_length));
1491+
reinterpret_cast<char*>(dst_buffer_data + offset),
1492+
std::min<uint32_t>(dst_size - offset, max_length));
15161493
}
15171494

15181495
static v8::CFunction fast_write_string_ascii(
@@ -1539,16 +1516,12 @@ void Initialize(Local<Object> target,
15391516
"byteLengthUtf8",
15401517
SlowByteLengthUtf8,
15411518
&fast_byte_length_utf8);
1542-
SetFastMethod(context, target, "copy", SlowCopy, &fast_copy);
1543-
SetFastMethodNoSideEffect(context, target, "compare", Compare, &fast_compare);
1519+
SetMethod(context, target, "copy", SlowCopy);
1520+
SetMethod(context, target, "compare", Compare);
15441521
SetMethodNoSideEffect(context, target, "compareOffset", CompareOffset);
15451522
SetMethod(context, target, "fill", Fill);
15461523
SetMethodNoSideEffect(context, target, "indexOfBuffer", IndexOfBuffer);
1547-
SetFastMethodNoSideEffect(context,
1548-
target,
1549-
"indexOfNumber",
1550-
SlowIndexOfNumber,
1551-
&fast_index_of_number);
1524+
SetMethodNoSideEffect(context, target, "indexOfNumber", IndexOfNumber);
15521525
SetMethodNoSideEffect(context, target, "indexOfString", IndexOfString);
15531526

15541527
SetMethod(context, target, "detachArrayBuffer", DetachArrayBuffer);
@@ -1618,14 +1591,10 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
16181591
registry->Register(fast_copy.GetTypeInfo());
16191592
registry->Register(FastCopy);
16201593
registry->Register(Compare);
1621-
registry->Register(FastCompare);
1622-
registry->Register(fast_compare.GetTypeInfo());
16231594
registry->Register(CompareOffset);
16241595
registry->Register(Fill);
16251596
registry->Register(IndexOfBuffer);
1626-
registry->Register(SlowIndexOfNumber);
1627-
registry->Register(FastIndexOfNumber);
1628-
registry->Register(fast_index_of_number.GetTypeInfo());
1597+
registry->Register(IndexOfNumber);
16291598
registry->Register(IndexOfString);
16301599

16311600
registry->Register(Swap16);

src/node_external_reference.h

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,6 @@ using CFunctionCallbackWithStrings =
3838
bool (*)(v8::Local<v8::Value>,
3939
const v8::FastOneByteString& input,
4040
const v8::FastOneByteString& base);
41-
using CFunctionCallbackWithTwoUint8Arrays =
42-
int32_t (*)(v8::Local<v8::Value>,
43-
const v8::FastApiTypedArray<uint8_t>&,
44-
const v8::FastApiTypedArray<uint8_t>&);
45-
using CFunctionCallbackWithTwoUint8ArraysFallback =
46-
bool (*)(v8::Local<v8::Value>,
47-
const v8::FastApiTypedArray<uint8_t>&,
48-
const v8::FastApiTypedArray<uint8_t>&,
49-
v8::FastApiCallbackOptions&);
50-
using CFunctionCallbackWithUint8ArrayUint32Int64Bool =
51-
int32_t (*)(v8::Local<v8::Value>,
52-
const v8::FastApiTypedArray<uint8_t>&,
53-
uint32_t,
54-
int64_t,
55-
bool);
5641
using CFunctionWithUint32 = uint32_t (*)(v8::Local<v8::Value>,
5742
const uint32_t input);
5843
using CFunctionWithDoubleReturnDouble = double (*)(v8::Local<v8::Value>,
@@ -68,18 +53,20 @@ using CFunctionWithBool = void (*)(v8::Local<v8::Value>,
6853

6954
using CFunctionWriteString =
7055
uint32_t (*)(v8::Local<v8::Value> receiver,
71-
const v8::FastApiTypedArray<uint8_t>& dst,
56+
v8::Local<v8::Value> dst,
7257
const v8::FastOneByteString& src,
7358
uint32_t offset,
74-
uint32_t max_length);
59+
uint32_t max_length,
60+
v8::FastApiCallbackOptions&);
7561

7662
using CFunctionBufferCopy =
7763
uint32_t (*)(v8::Local<v8::Value> receiver,
78-
const v8::FastApiTypedArray<uint8_t>& source,
79-
const v8::FastApiTypedArray<uint8_t>& target,
64+
v8::Local<v8::Value> source,
65+
v8::Local<v8::Value> target,
8066
uint32_t target_start,
8167
uint32_t source_start,
82-
uint32_t to_copy);
68+
uint32_t to_copy,
69+
v8::FastApiCallbackOptions&);
8370

8471
// This class manages the external references from the V8 heap
8572
// to the C++ addresses in Node.js.
@@ -98,9 +85,6 @@ class ExternalReferenceRegistry {
9885
V(CFunctionCallbackWithBool) \
9986
V(CFunctionCallbackWithString) \
10087
V(CFunctionCallbackWithStrings) \
101-
V(CFunctionCallbackWithTwoUint8Arrays) \
102-
V(CFunctionCallbackWithTwoUint8ArraysFallback) \
103-
V(CFunctionCallbackWithUint8ArrayUint32Int64Bool) \
10488
V(CFunctionWithUint32) \
10589
V(CFunctionWithDoubleReturnDouble) \
10690
V(CFunctionWithInt64Fallback) \

test/sequential/test-crypto-timing-safe-equal.js

Lines changed: 2 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -7,92 +7,6 @@ if (!common.hasCrypto)
77
const assert = require('assert');
88
const crypto = require('crypto');
99

10-
// 'should consider equal strings to be equal'
11-
assert.strictEqual(
12-
crypto.timingSafeEqual(Buffer.from('foo'), Buffer.from('foo')),
13-
true
14-
);
15-
16-
// 'should consider unequal strings to be unequal'
17-
assert.strictEqual(
18-
crypto.timingSafeEqual(Buffer.from('foo'), Buffer.from('bar')),
19-
false
20-
);
21-
22-
{
23-
// Test TypedArrays with different lengths but equal byteLengths.
24-
const buf = crypto.randomBytes(16).buffer;
25-
const a1 = new Uint8Array(buf);
26-
const a2 = new Uint16Array(buf);
27-
const a3 = new Uint32Array(buf);
28-
29-
for (const left of [a1, a2, a3]) {
30-
for (const right of [a1, a2, a3]) {
31-
assert.strictEqual(crypto.timingSafeEqual(left, right), true);
32-
}
33-
}
34-
}
35-
36-
{
37-
// When the inputs are floating-point numbers, timingSafeEqual neither has
38-
// equality nor SameValue semantics. It just compares the underlying bytes,
39-
// ignoring the TypedArray type completely.
40-
41-
const cmp = (fn) => (a, b) => a.every((x, i) => fn(x, b[i]));
42-
const eq = cmp((a, b) => a === b);
43-
const is = cmp(Object.is);
44-
45-
function test(a, b, { equal, sameValue, timingSafeEqual }) {
46-
assert.strictEqual(eq(a, b), equal);
47-
assert.strictEqual(is(a, b), sameValue);
48-
assert.strictEqual(crypto.timingSafeEqual(a, b), timingSafeEqual);
49-
}
50-
51-
test(new Float32Array([NaN]), new Float32Array([NaN]), {
52-
equal: false,
53-
sameValue: true,
54-
timingSafeEqual: true
55-
});
56-
57-
test(new Float64Array([0]), new Float64Array([-0]), {
58-
equal: true,
59-
sameValue: false,
60-
timingSafeEqual: false
61-
});
62-
63-
const x = new BigInt64Array([0x7ff0000000000001n, 0xfff0000000000001n]);
64-
test(new Float64Array(x.buffer), new Float64Array([NaN, NaN]), {
65-
equal: false,
66-
sameValue: true,
67-
timingSafeEqual: false
68-
});
69-
}
70-
71-
assert.throws(
72-
() => crypto.timingSafeEqual(Buffer.from([1, 2, 3]), Buffer.from([1, 2])),
73-
{
74-
code: 'ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH',
75-
name: 'RangeError',
76-
message: 'Input buffers must have the same byte length'
77-
}
78-
);
79-
80-
assert.throws(
81-
() => crypto.timingSafeEqual('not a buffer', Buffer.from([1, 2])),
82-
{
83-
code: 'ERR_INVALID_ARG_TYPE',
84-
name: 'TypeError',
85-
}
86-
);
87-
88-
assert.throws(
89-
() => crypto.timingSafeEqual(Buffer.from([1, 2]), 'not a buffer'),
90-
{
91-
code: 'ERR_INVALID_ARG_TYPE',
92-
name: 'TypeError',
93-
}
94-
);
95-
9610
{
9711
// V8 Fast API
9812
const foo = Buffer.from('foo');
@@ -113,7 +27,7 @@ assert.throws(
11327
if (common.isDebug) {
11428
const { internalBinding } = require('internal/test/binding');
11529
const { getV8FastApiCallCount } = internalBinding('debug');
116-
assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.ok'), 2);
117-
assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.error'), 1);
30+
assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.ok'), 0);
31+
assert.strictEqual(getV8FastApiCallCount('crypto.timingSafeEqual.error'), 0);
11832
}
11933
}

0 commit comments

Comments
 (0)