Skip to content

Commit 1916a77

Browse files
committedJan 27, 2025
8346923: MetaspaceShared base calculation may cause overflow in align_up
Reviewed-by: iklam, matsaave
1 parent 21feef3 commit 1916a77

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed
 

‎src/hotspot/share/cds/metaspaceShared.cpp

+45-12
Original file line numberDiff line numberDiff line change
@@ -214,47 +214,80 @@ void MetaspaceShared::dump_loaded_classes(const char* file_name, TRAPS) {
214214
}
215215
}
216216

217-
static bool shared_base_too_high(char* specified_base, char* aligned_base, size_t cds_max) {
218-
if (specified_base != nullptr && aligned_base < specified_base) {
219-
// SharedBaseAddress is very high (e.g., 0xffffffffffffff00) so
220-
// align_up(SharedBaseAddress, MetaspaceShared::core_region_alignment()) has wrapped around.
221-
return true;
217+
// If p is not aligned, move it up to the next address that's aligned with alignment.
218+
// If this is not possible (because p is too high), return nullptr. Example:
219+
// p = 0xffffffffffff0000, alignment= 0x10000 => return nullptr.
220+
static char* align_up_or_null(char* p, size_t alignment) {
221+
assert(p != nullptr, "sanity");
222+
if (is_aligned(p, alignment)) {
223+
return p;
224+
}
225+
226+
char* down = align_down(p, alignment);
227+
if (max_uintx - uintx(down) < uintx(alignment)) {
228+
// Run out of address space to align up.
229+
return nullptr;
222230
}
231+
232+
char* aligned = align_up(p, alignment);
233+
assert(aligned >= p, "sanity");
234+
assert(aligned != nullptr, "sanity");
235+
return aligned;
236+
}
237+
238+
static bool shared_base_too_high(char* specified_base, char* aligned_base, size_t cds_max) {
239+
// Caller should have checked if align_up_or_null( returns nullptr (comparing specified_base
240+
// with nullptr is UB).
241+
assert(aligned_base != nullptr, "sanity");
242+
assert(aligned_base >= specified_base, "sanity");
243+
223244
if (max_uintx - uintx(aligned_base) < uintx(cds_max)) {
224-
// The end of the archive will wrap around
245+
// Not enough address space to hold an archive of cds_max bytes from aligned_base.
225246
return true;
247+
} else {
248+
return false;
226249
}
227-
228-
return false;
229250
}
230251

231252
static char* compute_shared_base(size_t cds_max) {
232253
char* specified_base = (char*)SharedBaseAddress;
233-
char* aligned_base = align_up(specified_base, MetaspaceShared::core_region_alignment());
254+
size_t alignment = MetaspaceShared::core_region_alignment();
234255
if (UseCompressedClassPointers) {
235-
aligned_base = align_up(specified_base, Metaspace::reserve_alignment());
256+
alignment = MAX2(alignment, Metaspace::reserve_alignment());
236257
}
237258

259+
if (SharedBaseAddress == 0) {
260+
// Special meaning of -XX:SharedBaseAddress=0 -> Always map archive at os-selected address.
261+
return specified_base;
262+
}
263+
264+
char* aligned_base = align_up_or_null(specified_base, alignment);
265+
238266
if (aligned_base != specified_base) {
239267
log_info(cds)("SharedBaseAddress (" INTPTR_FORMAT ") aligned up to " INTPTR_FORMAT,
240268
p2i(specified_base), p2i(aligned_base));
241269
}
242270

243271
const char* err = nullptr;
244-
if (shared_base_too_high(specified_base, aligned_base, cds_max)) {
272+
if (aligned_base == nullptr) {
273+
err = "too high";
274+
} else if (shared_base_too_high(specified_base, aligned_base, cds_max)) {
245275
err = "too high";
246276
} else if (!shared_base_valid(aligned_base)) {
247277
err = "invalid for this platform";
248278
} else {
249279
return aligned_base;
250280
}
251281

282+
// Arguments::default_SharedBaseAddress() is hard-coded in cds_globals.hpp. It must be carefully
283+
// picked that (a) the align_up() below will always return a valid value; (b) none of
284+
// the following asserts will fail.
252285
log_warning(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is %s. Reverted to " INTPTR_FORMAT,
253286
p2i((void*)SharedBaseAddress), err,
254287
p2i((void*)Arguments::default_SharedBaseAddress()));
255288

256289
specified_base = (char*)Arguments::default_SharedBaseAddress();
257-
aligned_base = align_up(specified_base, MetaspaceShared::core_region_alignment());
290+
aligned_base = align_up(specified_base, alignment);
258291

259292
// Make sure the default value of SharedBaseAddress specified in globals.hpp is sane.
260293
assert(!shared_base_too_high(specified_base, aligned_base, cds_max), "Sanity");

0 commit comments

Comments
 (0)
Please sign in to comment.