mirror of https://github.com/nodejs/node.git
buffer: make `buflen` in integer range
This commit is contained in:
parent
885692a34f
commit
db80e6ebb8
|
@ -200,6 +200,13 @@ MaybeLocal<Value> ExternTwoByteString::NewSimpleFromCopy(Isolate* isolate,
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
static size_t keep_buflen_in_range(size_t len) {
|
||||
if (len > static_cast<size_t>(std::numeric_limits<int>::max())) {
|
||||
return static_cast<size_t>(std::numeric_limits<int>::max());
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t StringBytes::WriteUCS2(
|
||||
Isolate* isolate, char* buf, size_t buflen, Local<String> str, int flags) {
|
||||
uint16_t* const dst = reinterpret_cast<uint16_t*>(buf);
|
||||
|
@ -245,7 +252,7 @@ size_t StringBytes::Write(Isolate* isolate,
|
|||
enum encoding encoding) {
|
||||
HandleScope scope(isolate);
|
||||
size_t nbytes;
|
||||
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
CHECK(val->IsString() == true);
|
||||
Local<String> str = val.As<String>();
|
||||
|
||||
|
@ -545,6 +552,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
|
|||
}
|
||||
|
||||
case ASCII:
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
if (simdutf::validate_ascii_with_errors(buf, buflen).error) {
|
||||
// The input contains non-ASCII bytes.
|
||||
char* out = node::UncheckedMalloc(buflen);
|
||||
|
@ -558,23 +566,23 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
|
|||
return ExternOneByteString::NewFromCopy(isolate, buf, buflen, error);
|
||||
}
|
||||
|
||||
case UTF8:
|
||||
{
|
||||
val = String::NewFromUtf8(isolate,
|
||||
buf,
|
||||
v8::NewStringType::kNormal,
|
||||
buflen);
|
||||
Local<String> str;
|
||||
if (!val.ToLocal(&str)) {
|
||||
*error = node::ERR_STRING_TOO_LONG(isolate);
|
||||
}
|
||||
return str;
|
||||
case UTF8: {
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
val =
|
||||
String::NewFromUtf8(isolate, buf, v8::NewStringType::kNormal, buflen);
|
||||
Local<String> str;
|
||||
if (!val.ToLocal(&str)) {
|
||||
*error = node::ERR_STRING_TOO_LONG(isolate);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
case LATIN1:
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
return ExternOneByteString::NewFromCopy(isolate, buf, buflen, error);
|
||||
|
||||
case BASE64: {
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
size_t dlen = simdutf::base64_length_from_binary(buflen);
|
||||
char* dst = node::UncheckedMalloc(dlen);
|
||||
if (dst == nullptr) {
|
||||
|
@ -589,6 +597,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
|
|||
}
|
||||
|
||||
case BASE64URL: {
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
size_t dlen =
|
||||
simdutf::base64_length_from_binary(buflen, simdutf::base64_url);
|
||||
char* dst = node::UncheckedMalloc(dlen);
|
||||
|
@ -605,6 +614,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
|
|||
}
|
||||
|
||||
case HEX: {
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
size_t dlen = buflen * 2;
|
||||
char* dst = node::UncheckedMalloc(dlen);
|
||||
if (dst == nullptr) {
|
||||
|
@ -618,6 +628,7 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
|
|||
}
|
||||
|
||||
case UCS2: {
|
||||
buflen = keep_buflen_in_range(buflen);
|
||||
size_t str_len = buflen / 2;
|
||||
if constexpr (IsBigEndian()) {
|
||||
uint16_t* dst = node::UncheckedMalloc<uint16_t>(str_len);
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
|
||||
// Buffer with size > INT32_MAX
|
||||
common.skipIf32Bits();
|
||||
|
||||
// Test Buffer size larger than integer range
|
||||
const { test } = require('node:test');
|
||||
const assert = require('assert');
|
||||
const {
|
||||
SlowBuffer,
|
||||
} = require('buffer');
|
||||
const kStringMaxLength = require('buffer').constants.MAX_STRING_LENGTH;
|
||||
|
||||
const stringTooLongError = {
|
||||
message: `Cannot create a string longer than 0x${kStringMaxLength.toString(16)}` +
|
||||
' characters',
|
||||
code: 'ERR_STRING_TOO_LONG',
|
||||
name: 'Error',
|
||||
};
|
||||
|
||||
const size = 2 ** 31;
|
||||
|
||||
// Test Buffer.toString
|
||||
test('Buffer.toString with too long size', () => {
|
||||
try {
|
||||
assert.throws(() => SlowBuffer(size).toString('utf8'), stringTooLongError);
|
||||
assert.throws(() => Buffer.alloc(size).toString('utf8'), stringTooLongError);
|
||||
assert.throws(() => Buffer.allocUnsafe(size).toString('utf8'), stringTooLongError);
|
||||
assert.throws(() => Buffer.allocUnsafeSlow(size).toString('utf8'), stringTooLongError);
|
||||
} catch (e) {
|
||||
if (e.code !== 'ERR_MEMORY_ALLOCATION_FAILED') {
|
||||
throw e;
|
||||
}
|
||||
common.skip('insufficient space for Buffer.alloc');
|
||||
}
|
||||
});
|
||||
|
||||
// Test Buffer.write
|
||||
test('Buffer.write with too long size', () => {
|
||||
try {
|
||||
const buf = Buffer.alloc(size);
|
||||
assert.strictEqual(buf.write('a', 2, kStringMaxLength), 1);
|
||||
assert.strictEqual(buf.write('a', 2, size), 1);
|
||||
} catch (e) {
|
||||
if (e.code !== 'ERR_MEMORY_ALLOCATION_FAILED') {
|
||||
throw e;
|
||||
}
|
||||
common.skip('insufficient space for Buffer.alloc');
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue