Skip to content

Commit 290720d

Browse files
tniessentargos
authored andcommitted
napi: fix memory corruption vulnerability
Fixes: https://hackerone.com/reports/784186 CVE-ID: CVE-2020-8174 PR-URL: nodejs-private/node-private#195 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 07a4d50 commit 290720d

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

src/js_native_api_v8.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,7 +2177,7 @@ napi_status napi_get_value_string_latin1(napi_env env,
21772177
if (!buf) {
21782178
CHECK_ARG(env, result);
21792179
*result = val.As<v8::String>()->Length();
2180-
} else {
2180+
} else if (bufsize != 0) {
21812181
int copied =
21822182
val.As<v8::String>()->WriteOneByte(env->isolate,
21832183
reinterpret_cast<uint8_t*>(buf),
@@ -2189,6 +2189,8 @@ napi_status napi_get_value_string_latin1(napi_env env,
21892189
if (result != nullptr) {
21902190
*result = copied;
21912191
}
2192+
} else if (result != nullptr) {
2193+
*result = 0;
21922194
}
21932195

21942196
return napi_clear_last_error(env);
@@ -2216,7 +2218,7 @@ napi_status napi_get_value_string_utf8(napi_env env,
22162218
if (!buf) {
22172219
CHECK_ARG(env, result);
22182220
*result = val.As<v8::String>()->Utf8Length(env->isolate);
2219-
} else {
2221+
} else if (bufsize != 0) {
22202222
int copied = val.As<v8::String>()->WriteUtf8(
22212223
env->isolate,
22222224
buf,
@@ -2228,6 +2230,8 @@ napi_status napi_get_value_string_utf8(napi_env env,
22282230
if (result != nullptr) {
22292231
*result = copied;
22302232
}
2233+
} else if (result != nullptr) {
2234+
*result = 0;
22312235
}
22322236

22332237
return napi_clear_last_error(env);
@@ -2256,7 +2260,7 @@ napi_status napi_get_value_string_utf16(napi_env env,
22562260
CHECK_ARG(env, result);
22572261
// V8 assumes UTF-16 length is the same as the number of characters.
22582262
*result = val.As<v8::String>()->Length();
2259-
} else {
2263+
} else if (bufsize != 0) {
22602264
int copied = val.As<v8::String>()->Write(env->isolate,
22612265
reinterpret_cast<uint16_t*>(buf),
22622266
0,
@@ -2267,6 +2271,8 @@ napi_status napi_get_value_string_utf16(napi_env env,
22672271
if (result != nullptr) {
22682272
*result = copied;
22692273
}
2274+
} else if (result != nullptr) {
2275+
*result = 0;
22702276
}
22712277

22722278
return napi_clear_last_error(env);

test/js-native-api/test_string/test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,5 @@ assert.throws(() => {
8181
assert.throws(() => {
8282
test_string.TestLargeUtf16();
8383
}, /^Error: Invalid argument$/);
84+
85+
test_string.TestMemoryCorruption(' '.repeat(64 * 1024));

test/js-native-api/test_string/test_string.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <limits.h> // INT_MAX
2+
#include <string.h>
23
#include <js_native_api.h>
34
#include "../common.h"
45

@@ -244,6 +245,24 @@ static napi_value TestLargeUtf16(napi_env env, napi_callback_info info) {
244245
return output;
245246
}
246247

248+
static napi_value TestMemoryCorruption(napi_env env, napi_callback_info info) {
249+
size_t argc = 1;
250+
napi_value args[1];
251+
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
252+
253+
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
254+
255+
char buf[10] = { 0 };
256+
NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], buf, 0, NULL));
257+
258+
char zero[10] = { 0 };
259+
if (memcmp(buf, zero, sizeof(buf)) != 0) {
260+
NAPI_CALL(env, napi_throw_error(env, NULL, "Buffer overwritten"));
261+
}
262+
263+
return NULL;
264+
}
265+
247266
EXTERN_C_START
248267
napi_value Init(napi_env env, napi_value exports) {
249268
napi_property_descriptor properties[] = {
@@ -258,6 +277,7 @@ napi_value Init(napi_env env, napi_value exports) {
258277
DECLARE_NAPI_PROPERTY("TestLargeUtf8", TestLargeUtf8),
259278
DECLARE_NAPI_PROPERTY("TestLargeLatin1", TestLargeLatin1),
260279
DECLARE_NAPI_PROPERTY("TestLargeUtf16", TestLargeUtf16),
280+
DECLARE_NAPI_PROPERTY("TestMemoryCorruption", TestMemoryCorruption),
261281
};
262282

263283
NAPI_CALL(env, napi_define_properties(

0 commit comments

Comments
 (0)