Skip to content

Commit 0d5f47a

Browse files
committed
buffer: throw if string is not a valid HEX string
As it is, if an invalid HEX string is passed to `Buffer` constructor, it will only use the valid HEX values and ignore the rest. But, it also throws an error when the length of the string is odd in length. This patch throws an error if the string is not a valid HEX string. Fixes: #3770
1 parent 8ff9b56 commit 0d5f47a

File tree

3 files changed

+40
-4
lines changed

3 files changed

+40
-4
lines changed

src/node_buffer.cc

+5-3
Original file line numberDiff line numberDiff line change
@@ -622,9 +622,6 @@ void StringWrite(const FunctionCallbackInfo<Value>& args) {
622622

623623
Local<String> str = args[0]->ToString(env->isolate());
624624

625-
if (encoding == HEX && str->Length() % 2 != 0)
626-
return env->ThrowTypeError("Invalid hex string");
627-
628625
size_t offset;
629626
size_t max_length;
630627

@@ -639,6 +636,11 @@ void StringWrite(const FunctionCallbackInfo<Value>& args) {
639636
if (offset >= ts_obj_length)
640637
return env->ThrowRangeError("Offset is out of bounds");
641638

639+
if (StringBytes::IsValidString(env->isolate(), str, encoding) == false) {
640+
if (encoding == HEX)
641+
return env->ThrowTypeError("Invalid hex string");
642+
}
643+
642644
uint32_t written = StringBytes::Write(env->isolate(),
643645
ts_obj_data + offset,
644646
max_length,

src/string_bytes.cc

+26-1
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,36 @@ size_t StringBytes::Write(Isolate* isolate,
451451
return nbytes;
452452
}
453453

454+
template <typename Type>
455+
bool IsValidHexString(Isolate* isolate, const Type* str, const size_t len) {
456+
for (size_t i = 0; i < len; i += 1) {
457+
if (!((str[i] >= '0' && str[i] <= '9') ||
458+
(str[i] >= 'a' && str[i] <= 'f') ||
459+
(str[i] >= 'A' && str[i] <= 'F')))
460+
return false;
461+
}
462+
return true;
463+
}
464+
465+
bool IsValidHexString(Isolate* isolate, Local<String> string) {
466+
if (string->Length() % 2 != 0)
467+
return false;
468+
469+
const char* str = nullptr;
470+
size_t n = 0;
471+
bool external = StringBytes::GetExternalParts(isolate, string, &str, &n);
472+
473+
if (external)
474+
return IsValidHexString(isolate, str, n);
475+
476+
String::Value value(string);
477+
return IsValidHexString(isolate, *value, value.length());
478+
}
454479

455480
bool StringBytes::IsValidString(Isolate* isolate,
456481
Local<String> string,
457482
enum encoding enc) {
458-
if (enc == HEX && string->Length() % 2 != 0)
483+
if (enc == HEX && IsValidHexString(isolate, string) == false)
459484
return false;
460485
// TODO(bnoordhuis) Add BASE64 check?
461486
return true;

test/parallel/test-buffer.js

+9
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,15 @@ for (let i = 0; i < 256; i++) {
741741
assert.equal(b2, b4);
742742
}
743743

744+
// invalid HEX strings should throw an error
745+
assert.throws(() => new Buffer('xx', 'hex'), /TypeError: Invalid hex string/);
746+
// following will fail even though it has zero as the first character, because
747+
// `x` is an invalid hexa-decimal value
748+
assert.throws(() => new Buffer('0x', 'hex'), /TypeError: Invalid hex string/);
749+
// following invalid HEX strings will fail because of the odd length
750+
assert.throws(() => new Buffer('0', 'hex'), /TypeError: Invalid hex string/);
751+
assert.throws(() => new Buffer('000', 'hex'), /TypeError: Invalid hex string/);
752+
744753
function buildBuffer(data) {
745754
if (Array.isArray(data)) {
746755
var buffer = new Buffer(data.length);

0 commit comments

Comments
 (0)