Skip to content

Commit 8f28809

Browse files
committed
8299790: os::print_hex_dump is racy
Reviewed-by: shade, dholmes
1 parent e080a0b commit 8f28809

File tree

2 files changed

+68
-27
lines changed

2 files changed

+68
-27
lines changed

Diff for: src/hotspot/share/runtime/os.cpp

+53-12
Original file line numberDiff line numberDiff line change
@@ -928,13 +928,58 @@ bool os::print_function_and_library_name(outputStream* st,
928928
return have_function_name || have_library_name;
929929
}
930930

931-
ATTRIBUTE_NO_ASAN static void print_hex_readable_pointer(outputStream* st, address p,
932-
int unitsize) {
933-
switch (unitsize) {
934-
case 1: st->print("%02x", *(u1*)p); break;
935-
case 2: st->print("%04x", *(u2*)p); break;
936-
case 4: st->print("%08x", *(u4*)p); break;
937-
case 8: st->print("%016" FORMAT64_MODIFIER "x", *(u8*)p); break;
931+
ATTRIBUTE_NO_ASAN static bool read_safely_from(intptr_t* p, intptr_t* result) {
932+
const intptr_t errval = 0x1717;
933+
intptr_t i = SafeFetchN(p, errval);
934+
if (i == errval) {
935+
i = SafeFetchN(p, ~errval);
936+
if (i == ~errval) {
937+
return false;
938+
}
939+
}
940+
(*result) = i;
941+
return true;
942+
}
943+
944+
static void print_hex_location(outputStream* st, address p, int unitsize) {
945+
address pa = align_down(p, sizeof(intptr_t));
946+
#ifndef _LP64
947+
// Special handling for printing qwords on 32-bit platforms
948+
if (unitsize == 8) {
949+
intptr_t i1, i2;
950+
if (read_safely_from((intptr_t*)pa, &i1) &&
951+
read_safely_from((intptr_t*)pa + 1, &i2)) {
952+
const uint64_t value =
953+
LITTLE_ENDIAN_ONLY((((uint64_t)i2) << 32) | i1)
954+
BIG_ENDIAN_ONLY((((uint64_t)i1) << 32) | i2);
955+
st->print("%016" FORMAT64_MODIFIER "x", value);
956+
} else {
957+
st->print_raw("????????????????");
958+
}
959+
return;
960+
}
961+
#endif // 32-bit, qwords
962+
intptr_t i = 0;
963+
if (read_safely_from((intptr_t*)pa, &i)) {
964+
const int offset = (int)(p - (address)pa);
965+
const int bitoffset =
966+
LITTLE_ENDIAN_ONLY(offset * BitsPerByte)
967+
BIG_ENDIAN_ONLY((int)(sizeof(intptr_t) - 1 - offset) * BitsPerByte);
968+
const int bitfieldsize = unitsize * BitsPerByte;
969+
intptr_t value = bitfield(i, bitoffset, bitfieldsize);
970+
switch (unitsize) {
971+
case 1: st->print("%02x", (u1)value); break;
972+
case 2: st->print("%04x", (u2)value); break;
973+
case 4: st->print("%08x", (u4)value); break;
974+
case 8: st->print("%016" FORMAT64_MODIFIER "x", (u8)value); break;
975+
}
976+
} else {
977+
switch (unitsize) {
978+
case 1: st->print_raw("??"); break;
979+
case 2: st->print_raw("????"); break;
980+
case 4: st->print_raw("????????"); break;
981+
case 8: st->print_raw("????????????????"); break;
982+
}
938983
}
939984
}
940985

@@ -955,11 +1000,7 @@ void os::print_hex_dump(outputStream* st, address start, address end, int unitsi
9551000
// Print out the addresses as if we were starting from logical_start.
9561001
st->print(PTR_FORMAT ": ", p2i(logical_p));
9571002
while (p < end) {
958-
if (is_readable_pointer(p)) {
959-
print_hex_readable_pointer(st, p, unitsize);
960-
} else {
961-
st->print("%*.*s", 2*unitsize, 2*unitsize, "????????????????");
962-
}
1003+
print_hex_location(st, p, unitsize);
9631004
p += unitsize;
9641005
logical_p += unitsize;
9651006
cols++;

Diff for: test/hotspot/gtest/runtime/test_os.cpp

+15-15
Original file line numberDiff line numberDiff line change
@@ -169,31 +169,31 @@ static void do_test_print_hex_dump(address addr, size_t len, int unitsize, const
169169
buf[0] = '\0';
170170
stringStream ss(buf, sizeof(buf));
171171
os::print_hex_dump(&ss, addr, addr + len, unitsize);
172-
// tty->print_cr("expected: %s", expected);
173-
// tty->print_cr("result: %s", buf);
174-
ASSERT_NE(strstr(buf, expected), (char*)NULL);
172+
// tty->print_cr("expected: %s", expected);
173+
// tty->print_cr("result: %s", buf);
174+
EXPECT_THAT(buf, testing::HasSubstr(expected));
175175
}
176176

177177
TEST_VM(os, test_print_hex_dump) {
178178
const char* pattern [4] = {
179179
#ifdef VM_LITTLE_ENDIAN
180-
"00 01 02 03 04 05 06 07",
181-
"0100 0302 0504 0706",
182-
"03020100 07060504",
183-
"0706050403020100"
180+
"00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f",
181+
"0100 0302 0504 0706 0908 0b0a 0d0c 0f0e",
182+
"03020100 07060504 0b0a0908 0f0e0d0c",
183+
"0706050403020100 0f0e0d0c0b0a0908"
184184
#else
185-
"00 01 02 03 04 05 06 07",
186-
"0001 0203 0405 0607",
187-
"00010203 04050607",
188-
"0001020304050607"
185+
"00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f",
186+
"0001 0203 0405 0607 0809 0a0b 0c0d 0e0f",
187+
"00010203 04050607 08090a0b 0c0d0e0f",
188+
"0001020304050607 08090a0b0c0d0e0f"
189189
#endif
190190
};
191191

192192
const char* pattern_not_readable [4] = {
193-
"?? ?? ?? ?? ?? ?? ?? ??",
194-
"???? ???? ???? ????",
195-
"???????? ????????",
196-
"????????????????"
193+
"?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??",
194+
"???? ???? ???? ???? ???? ???? ???? ????",
195+
"???????? ???????? ???????? ????????",
196+
"???????????????? ????????????????"
197197
};
198198

199199
// On AIX, zero page is readable.

0 commit comments

Comments
 (0)