Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.

Commit f5ab7f6

Browse files
committed
8262472: Buffer overflow in UNICODE::as_utf8 for zero length output buffer
Reviewed-by: dholmes, iklam
1 parent 6635d7a commit f5ab7f6

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/hotspot/share/utilities/utf8.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ char* UNICODE::as_utf8(const T* base, int& length) {
447447
}
448448

449449
char* UNICODE::as_utf8(const jchar* base, int length, char* buf, int buflen) {
450+
assert(buflen > 0, "zero length output buffer");
450451
u_char* p = (u_char*)buf;
451452
for (int index = 0; index < length; index++) {
452453
jchar c = base[index];
@@ -459,6 +460,7 @@ char* UNICODE::as_utf8(const jchar* base, int length, char* buf, int buflen) {
459460
}
460461

461462
char* UNICODE::as_utf8(const jbyte* base, int length, char* buf, int buflen) {
463+
assert(buflen > 0, "zero length output buffer");
462464
u_char* p = (u_char*)buf;
463465
for (int index = 0; index < length; index++) {
464466
jbyte c = base[index];

test/hotspot/gtest/utilities/test_utf8.cpp

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,22 @@
2525
#include "utilities/utf8.hpp"
2626
#include "unittest.hpp"
2727

28-
TEST(utf8, length) {
28+
static void stamp(char* p, size_t len) {
29+
if (len > 0) {
30+
::memset(p, 'A', len);
31+
}
32+
}
33+
34+
static bool test_stamp(const char* p, size_t len) {
35+
for (const char* q = p; q < p + len; q++) {
36+
if (*q != 'A') {
37+
return false;
38+
}
39+
}
40+
return true;
41+
}
42+
43+
TEST_VM(utf8, jchar_length) {
2944
char res[60];
3045
jchar str[20];
3146

@@ -35,16 +50,56 @@ TEST(utf8, length) {
3550
str[19] = (jchar) '\0';
3651

3752
// The resulting string in UTF-8 is 3*19 bytes long, but should be truncated
53+
stamp(res, sizeof(res));
3854
UNICODE::as_utf8(str, 19, res, 10);
3955
ASSERT_EQ(strlen(res), (size_t) 9) << "string should be truncated here";
56+
ASSERT_TRUE(test_stamp(res + 10, sizeof(res) - 10));
4057

58+
stamp(res, sizeof(res));
4159
UNICODE::as_utf8(str, 19, res, 18);
4260
ASSERT_EQ(strlen(res), (size_t) 15) << "string should be truncated here";
61+
ASSERT_TRUE(test_stamp(res + 18, sizeof(res) - 18));
4362

63+
stamp(res, sizeof(res));
4464
UNICODE::as_utf8(str, 19, res, 20);
4565
ASSERT_EQ(strlen(res), (size_t) 18) << "string should be truncated here";
66+
ASSERT_TRUE(test_stamp(res + 20, sizeof(res) - 20));
4667

4768
// Test with an "unbounded" buffer
4869
UNICODE::as_utf8(str, 19, res, INT_MAX);
4970
ASSERT_EQ(strlen(res), (size_t) 3 * 19) << "string should end here";
71+
72+
// Test that we do not overflow the output buffer
73+
for (int i = 1; i < 5; i ++) {
74+
stamp(res, sizeof(res));
75+
UNICODE::as_utf8(str, 19, res, i);
76+
EXPECT_TRUE(test_stamp(res + i, sizeof(res) - i));
77+
}
78+
79+
}
80+
81+
TEST_VM(utf8, jbyte_length) {
82+
char res[60];
83+
jbyte str[20];
84+
85+
for (int i = 0; i < 19; i++) {
86+
str[i] = 0x42;
87+
}
88+
str[19] = '\0';
89+
90+
stamp(res, sizeof(res));
91+
UNICODE::as_utf8(str, 19, res, 10);
92+
ASSERT_EQ(strlen(res), (size_t) 9) << "string should be truncated here";
93+
ASSERT_TRUE(test_stamp(res + 10, sizeof(res) - 10));
94+
95+
UNICODE::as_utf8(str, 19, res, INT_MAX);
96+
ASSERT_EQ(strlen(res), (size_t) 19) << "string should end here";
97+
98+
// Test that we do not overflow the output buffer
99+
for (int i = 1; i < 5; i ++) {
100+
stamp(res, sizeof(res));
101+
UNICODE::as_utf8(str, 19, res, i);
102+
EXPECT_TRUE(test_stamp(res + i, sizeof(res) - i));
103+
}
104+
50105
}

0 commit comments

Comments
 (0)