diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index f680939682a..9483c6715b4 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -344,8 +344,19 @@ Symbol* SymbolTable::lookup_common(const char* name, return sym; } +// Symbols should represent entities from the constant pool that are +// limited to 64K in length, but usage errors creep in allowing Symbols +// to be used for arbitrary strings. For debug builds we will assert if +// a string is too long, whereas product builds will truncate it. Symbol* SymbolTable::new_symbol(const char* name, int len) { - assert(len <= Symbol::max_length(), "sanity"); + assert(len <= Symbol::max_length(), + "String length %d exceeds the maximum Symbol length of %d", len, Symbol::max_length()); + if (len > Symbol::max_length()) { + warning("A string \"%.80s ... %.80s\" exceeds the maximum Symbol " + "length of %d and has been truncated", name, (name + len - 80), Symbol::max_length()); + len = Symbol::max_length(); + } + unsigned int hash = hash_symbol(name, len, _alt_hash); Symbol* sym = lookup_common(name, len, hash); if (sym == nullptr) { @@ -485,6 +496,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa for (int i = 0; i < names_count; i++) { const char *name = names[i]; int len = lengths[i]; + assert(len <= Symbol::max_length(), "must be - these come from the constant pool"); unsigned int hash = hashValues[i]; assert(lookup_shared(name, len, hash) == nullptr, "must have checked already"); Symbol* sym = do_add_if_needed(name, len, hash, is_permanent); @@ -494,6 +506,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa } Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool is_permanent) { + assert(len <= Symbol::max_length(), "caller should have ensured this"); SymbolTableLookup lookup(name, len, hash); SymbolTableGet stg; bool clean_hint = false; diff --git a/src/hotspot/share/oops/symbol.cpp b/src/hotspot/share/oops/symbol.cpp index 4deae372061..8fe7c2aadbf 100644 --- a/src/hotspot/share/oops/symbol.cpp +++ b/src/hotspot/share/oops/symbol.cpp @@ -54,6 +54,7 @@ uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) { } Symbol::Symbol(const u1* name, int length, int refcount) { + assert(length <= max_length(), "SymbolTable should have caught this!"); _hash_and_refcount = pack_hash_and_refcount((short)os::random(), refcount); _length = (u2)length; // _body[0..1] are allocated in the header just by coincidence in the current diff --git a/src/hotspot/share/oops/symbol.hpp b/src/hotspot/share/oops/symbol.hpp index 3b3f1366203..045332c7a84 100644 --- a/src/hotspot/share/oops/symbol.hpp +++ b/src/hotspot/share/oops/symbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -130,6 +130,7 @@ class Symbol : public MetaspaceObj { return (int)heap_word_size(byte_size(length)); } + // Constructor is private for use only by SymbolTable. Symbol(const u1* name, int length, int refcount); static short extract_hash(uint32_t value) { return (short)(value >> 16); }