From b98114f4a20bcf3390114b56d05c38b23268979a Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 1 Dec 2025 13:28:21 +0000 Subject: [PATCH] 8365526: Crash with null Symbol passed to SystemDictionary::resolve_or_null Reviewed-by: dholmes, never, jsjolen --- src/hotspot/share/classfile/resolutionErrors.cpp | 13 +++++++++++-- src/hotspot/share/classfile/resolutionErrors.hpp | 7 ++----- src/hotspot/share/classfile/systemDictionary.cpp | 13 +++++++++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp index 25aa370d257..f5a335f17f3 100644 --- a/src/hotspot/share/classfile/resolutionErrors.cpp +++ b/src/hotspot/share/classfile/resolutionErrors.cpp @@ -73,7 +73,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde ResolutionErrorKey key(pool(), cp_index); ResolutionErrorEntry *entry = new ResolutionErrorEntry(error, message, cause, cause_msg); - _resolution_error_table->put(key, entry); + _resolution_error_table->put_when_absent(key, entry); } // create new nest host error entry @@ -85,7 +85,7 @@ void ResolutionErrorTable::add_entry(const constantPoolHandle& pool, int cp_inde ResolutionErrorKey key(pool(), cp_index); ResolutionErrorEntry *entry = new ResolutionErrorEntry(message); - _resolution_error_table->put(key, entry); + _resolution_error_table->put_when_absent(key, entry); } // find entry in the table @@ -126,6 +126,15 @@ ResolutionErrorEntry::~ResolutionErrorEntry() { } } +void ResolutionErrorEntry::set_nest_host_error(const char* message) { + // If a message is already set, free it. + if (nest_host_error() != nullptr) { + FREE_C_HEAP_ARRAY(char, _nest_host_error); + } + _nest_host_error = message; +} + + class ResolutionErrorDeleteIterate : StackObj { ConstantPool* p; diff --git a/src/hotspot/share/classfile/resolutionErrors.hpp b/src/hotspot/share/classfile/resolutionErrors.hpp index 60f8aea68ef..39859ad2b70 100644 --- a/src/hotspot/share/classfile/resolutionErrors.hpp +++ b/src/hotspot/share/classfile/resolutionErrors.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,10 +91,7 @@ class ResolutionErrorEntry : public CHeapObj { ~ResolutionErrorEntry(); // The incoming nest host error message is already in the C-Heap. - void set_nest_host_error(const char* message) { - _nest_host_error = message; - } - + void set_nest_host_error(const char* message); Symbol* error() const { return _error; } const char* message() const { return _message; } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 5c49a32b8d0..a17e7e129ce 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1864,14 +1864,19 @@ void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool, { MutexLocker ml(Thread::current(), SystemDictionary_lock); ResolutionErrorEntry* entry = ResolutionErrorTable::find_entry(pool, which); - if (entry != nullptr && entry->nest_host_error() == nullptr) { + if (entry == nullptr) { + // Only add a new entry to the resolution error table if one hasn't been found for this + // constant pool index. In this case resolution succeeded but there's an error in this nest host + // that we use the table to record. + assert(pool->resolved_klass_at(which) != nullptr, "klass should be resolved if there is no entry"); + ResolutionErrorTable::add_entry(pool, which, message); + } else { // An existing entry means we had a true resolution failure (LinkageError) with our nest host, but we // still want to add the error message for the higher-level access checks to report. We should // only reach here under the same error condition, so we can ignore the potential race with setting - // the message. If we see it is already set then we can ignore it. + // the message, and set it again. + assert(entry->nest_host_error() == nullptr || strcmp(entry->nest_host_error(), message) == 0, "should be the same message"); entry->set_nest_host_error(message); - } else { - ResolutionErrorTable::add_entry(pool, which, message); } } }