RFR: 8289046: Undefined Behaviour in x86 class Assembler
Aleksey Shipilev
shade at openjdk.org
Thu Jun 23 15:20:49 UTC 2022
On Thu, 23 Jun 2022 14:52:54 GMT, Andrew Haley <aph at openjdk.org> wrote:
> All instances of type Register exhibit UB in the form of wild pointer (including null pointer) dereferences. This isn't very hard to fix: we should make Registers pointers to something rather than aliases of small integers.
>
> Here's an example of what was happening:
>
> ` rax->encoding();`
>
> Where rax is defined as `(Register *)0`.
>
> This patch things so that rax is now defined as a pointer to the start of a static array of RegisterImpl.
>
>
> typedef const RegisterImpl* Register;
> extern RegisterImpl all_Registers[RegisterImpl::number_of_declared_registers + 1] ;
> inline constexpr Register RegisterImpl::first() { return all_Registers + 1; };
> inline constexpr Register as_Register(int encoding) { return RegisterImpl::first() + encoding; }
> constexpr Register rax = as_register(0);
Cursory review:
src/hotspot/cpu/x86/globalDefinitions_x86.hpp line 78:
> 76: #endif
> 77:
> 78: #define USE_POINTERS_TO_REGISTER_IMPL_ARRAY
So, what's the use for this symbol? I see AArch64 code conditionalize definition macros, but this patch does not have such conditionalization. Should it?
src/hotspot/cpu/x86/register_x86.hpp line 70:
> 68: // accessors
> 69: int raw_encoding() const { return this - first(); }
> 70: int encoding() const { assert(is_valid(), "invalid register"); return (this - first()); }
Suggestion:
int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
src/hotspot/cpu/x86/register_x86.hpp line 76:
> 74: };
> 75:
> 76: // The implementation of integer registers for the ia32 architecture
This comment seems unrelated, copy-paste error?
src/hotspot/cpu/x86/register_x86.hpp line 130:
> 128: // accessors
> 129: int raw_encoding() const { return this - first(); }
> 130: int encoding() const { assert(is_valid(), "invalid register"); return this - first(); }
Suggestion:
int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); }
src/hotspot/cpu/x86/register_x86.hpp line 171:
> 169: // accessors
> 170: int raw_encoding() const { return this - first(); }
> 171: int encoding() const { assert(is_valid(), "invalid register (%d)", (int)raw_encoding() ); return raw_encoding(); }
In the other cases, we don't do this kind of printing assert. Stick to one style? I think it is fine to have a shorter assert, because `!is_valid()` basically implies `noreg`?
-------------
Changes requested by shade (Reviewer).
PR: https://git.openjdk.org/jdk/pull/9261
More information about the hotspot-compiler-dev
mailing list