8328698: oopDesc::klass_raw() decodes without a null check

Reviewed-by: ayang, tschatzl
This commit is contained in:
Stefan Karlsson 2024-04-08 09:29:40 +00:00
parent d1aad71209
commit 6f087cbcd5
10 changed files with 62 additions and 54 deletions

@ -248,7 +248,7 @@ inline bool G1CollectedHeap::requires_barriers(stackChunkOop obj) const {
}
inline bool G1CollectedHeap::is_obj_filler(const oop obj) {
Klass* k = obj->klass_raw();
Klass* k = obj->klass_without_asserts();
return k == Universe::fillerArrayKlass() || k == vmClasses::FillerObject_klass();
}

@ -433,25 +433,33 @@ void HeapRegion::print_on(outputStream* st) const {
}
static bool is_oop_safe(oop obj) {
if (!oopDesc::is_oop(obj)) {
log_error(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
// Make a few sanity checks of the class before calling the full-fledged
// is_oop check (which also performs its own klass verification).
Klass* klass = obj->klass_without_asserts();
if (klass == nullptr) {
log_error(gc, verify)("Object " PTR_FORMAT " has a null klass", p2i(obj));
return false;
}
// Now examine the Klass a little more closely.
Klass* klass = obj->klass_raw();
bool is_metaspace_object = Metaspace::contains(klass);
if (!is_metaspace_object) {
if (!Metaspace::contains(klass)) {
log_error(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
"not metadata", p2i(klass), p2i(obj));
"is not in metaspace", p2i(klass), p2i(obj));
return false;
} else if (!klass->is_klass()) {
}
if (!klass->is_klass()) {
log_error(gc, verify)("klass " PTR_FORMAT " of object " PTR_FORMAT " "
"not a klass", p2i(klass), p2i(obj));
return false;
}
// Now, perform the more in-depth verification of the object.
if (!oopDesc::is_oop(obj)) {
log_error(gc, verify)(PTR_FORMAT " not an oop", p2i(obj));
return false;
}
return true;
}

@ -229,7 +229,7 @@ bool CollectedHeap::is_oop(oop object) const {
return false;
}
if (!Metaspace::contains(object->klass_raw())) {
if (!Metaspace::contains(object->klass_without_asserts())) {
return false;
}

@ -28,6 +28,7 @@
#include "memory/universe.hpp"
#include "runtime/os.hpp"
#include "oops/klass.hpp"
#include "oops/oop.inline.hpp"
bool LocationPrinter::is_valid_obj(void* obj) {
if (!is_object_aligned(obj)) {
@ -45,6 +46,6 @@ bool LocationPrinter::is_valid_obj(void* obj) {
return false;
}
Klass* k = (Klass*)oopDesc::load_klass_raw((oopDesc*)obj);
Klass* k = ((oopDesc*)obj)->klass_without_asserts();
return Klass::is_valid(k);
}

@ -45,6 +45,7 @@ const uint64_t KlassEncodingMetaspaceMax = (uint64_t(max_juint) + 1) << LogKlas
// For UseCompressedClassPointers.
class CompressedKlassPointers : public AllStatic {
friend class VMStructs;
friend class ArchiveBuilder;
static address _base;
static int _shift;
@ -64,6 +65,11 @@ class CompressedKlassPointers : public AllStatic {
DEBUG_ONLY(static void assert_is_valid_encoding(address addr, size_t len, address base, int shift);)
static inline Klass* decode_not_null_without_asserts(narrowKlass v, address base, int shift);
static inline Klass* decode_not_null(narrowKlass v, address base, int shift);
static inline narrowKlass encode_not_null(Klass* v, address base, int shift);
public:
// Reserve a range of memory that is to contain Klass strucutures which are referenced by narrow Klass IDs.
@ -92,15 +98,15 @@ public:
static bool is_null(Klass* v) { return v == nullptr; }
static bool is_null(narrowKlass v) { return v == 0; }
static inline Klass* decode_raw(narrowKlass v, address base, int shift);
static inline Klass* decode_raw(narrowKlass v);
static inline Klass* decode_not_null(narrowKlass v);
static inline Klass* decode_not_null(narrowKlass v, address base, int shift);
static inline Klass* decode(narrowKlass v);
static inline narrowKlass encode_not_null(Klass* v);
static inline narrowKlass encode_not_null(Klass* v, address base, int shift);
static inline narrowKlass encode(Klass* v);
// Versions without asserts
static inline Klass* decode_not_null_without_asserts(narrowKlass v);
static inline Klass* decode_without_asserts(narrowKlass v);
static inline Klass* decode_not_null(narrowKlass v);
static inline Klass* decode(narrowKlass v);
static inline narrowKlass encode_not_null(Klass* v);
static inline narrowKlass encode(Klass* v);
};
#endif // SHARE_OOPS_COMPRESSEDKLASS_HPP

@ -36,33 +36,17 @@ static inline bool check_alignment(Klass* v) {
return (intptr_t)v % KlassAlignmentInBytes == 0;
}
inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v) {
return decode_raw(v, base(), shift());
}
inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v, address narrow_base, int shift) {
inline Klass* CompressedKlassPointers::decode_not_null_without_asserts(narrowKlass v, address narrow_base, int shift) {
return (Klass*)((uintptr_t)narrow_base +((uintptr_t)v << shift));
}
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v) {
return decode_not_null(v, base(), shift());
}
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v, address narrow_base, int shift) {
assert(!is_null(v), "narrow klass value can never be zero");
Klass* result = decode_raw(v, narrow_base, shift);
Klass* result = decode_not_null_without_asserts(v, narrow_base, shift);
assert(check_alignment(result), "address not aligned: " PTR_FORMAT, p2i(result));
return result;
}
inline Klass* CompressedKlassPointers::decode(narrowKlass v) {
return is_null(v) ? nullptr : decode_not_null(v);
}
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v) {
return encode_not_null(v, base(), shift());
}
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v, address narrow_base, int shift) {
assert(!is_null(v), "klass value can never be zero");
assert(check_alignment(v), "Address not aligned");
@ -74,6 +58,26 @@ inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v, address na
return (narrowKlass)result;
}
inline Klass* CompressedKlassPointers::decode_not_null_without_asserts(narrowKlass v) {
return decode_not_null_without_asserts(v, base(), shift());
}
inline Klass* CompressedKlassPointers::decode_without_asserts(narrowKlass v) {
return is_null(v) ? nullptr : decode_not_null_without_asserts(v);
}
inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v) {
return decode_not_null(v, base(), shift());
}
inline Klass* CompressedKlassPointers::decode(narrowKlass v) {
return is_null(v) ? nullptr : decode_not_null(v);
}
inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v) {
return encode_not_null(v, base(), shift());
}
inline narrowKlass CompressedKlassPointers::encode(Klass* v) {
return is_null(v) ? (narrowKlass)0 : encode_not_null(v);
}

@ -165,16 +165,6 @@ void oopDesc::set_narrow_klass(narrowKlass nk) {
}
#endif
void* oopDesc::load_klass_raw(oop obj) {
if (UseCompressedClassPointers) {
narrowKlass narrow_klass = obj->_metadata._compressed_klass;
if (narrow_klass == 0) return nullptr;
return (void*)CompressedKlassPointers::decode_raw(narrow_klass);
} else {
return obj->_metadata._klass;
}
}
void* oopDesc::load_oop_raw(oop obj, int offset) {
uintptr_t addr = (uintptr_t)(void*)obj + (uint)offset;
if (UseCompressedOops) {

@ -85,8 +85,8 @@ class oopDesc {
inline Klass* klass() const;
inline Klass* klass_or_null() const;
inline Klass* klass_or_null_acquire() const;
// Get the raw value without any checks.
inline Klass* klass_raw() const;
// Get the klass without running any asserts.
inline Klass* klass_without_asserts() const;
void set_narrow_klass(narrowKlass nk) NOT_CDS_JAVA_HEAP_RETURN;
inline void set_klass(Klass* k);
@ -316,7 +316,6 @@ class oopDesc {
}
// for error reporting
static void* load_klass_raw(oop obj);
static void* load_oop_raw(oop obj, int offset);
DEBUG_ONLY(bool size_might_change();)

@ -111,9 +111,9 @@ Klass* oopDesc::klass_or_null_acquire() const {
}
}
Klass* oopDesc::klass_raw() const {
Klass* oopDesc::klass_without_asserts() const {
if (UseCompressedClassPointers) {
return CompressedKlassPointers::decode_raw(_metadata._compressed_klass);
return CompressedKlassPointers::decode_without_asserts(_metadata._compressed_klass);
} else {
return _metadata._klass;
}

@ -1256,7 +1256,7 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
#ifdef _LP64
if (UseCompressedClassPointers && ((uintptr_t)addr &~ (uintptr_t)max_juint) == 0) {
narrowKlass narrow_klass = (narrowKlass)(uintptr_t)addr;
Klass* k = CompressedKlassPointers::decode_raw(narrow_klass);
Klass* k = CompressedKlassPointers::decode_without_asserts(narrow_klass);
if (Klass::is_valid(k)) {
st->print_cr(UINT32_FORMAT " is a compressed pointer to class: " INTPTR_FORMAT, narrow_klass, p2i((HeapWord*)k));