From c144d4353154b809c1f6b6202f25353471b84340 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Wed, 6 Feb 2019 06:21:21 +0000 Subject: [PATCH] Add backport of JDK-8145096 (PR3693) to fix undefined behaviour issues on newer GCCs --- java-1.8.0-openjdk.spec | 10 +- jdk8145096-pr3693-undefined_behaviour.patch | 280 ++++++++++++++++++++ 2 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 jdk8145096-pr3693-undefined_behaviour.patch diff --git a/java-1.8.0-openjdk.spec b/java-1.8.0-openjdk.spec index e2f12be..2b9b5d5 100644 --- a/java-1.8.0-openjdk.spec +++ b/java-1.8.0-openjdk.spec @@ -971,7 +971,7 @@ Provides: java-%{javaver}-%{origin}-accessibility = %{epoch}:%{version}-%{releas Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 1%{?dist} +Release: 2%{?dist} # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1222,6 +1222,8 @@ Patch587: jdk8164920-pr3574-rh1498936-ppc_crc32_enhancement.patch ############################################# # JDK-8029661, PR3642, RH1477159: Support TLS v1.2 algorithm in SunPKCS11 provider Patch585: jdk8029661-pr3642-rh1477159-add_tlsv1_2_support_to_pkcs11_provider.patch +# JDK-8145096, PR3693: Undefined behaviour in HotSpot +Patch588: jdk8145096-pr3693-undefined_behaviour.patch ############################################# # @@ -1638,6 +1640,7 @@ sh %{SOURCE12} %patch585 %patch586 %patch587 +%patch588 # RPM-only fixes %patch525 @@ -2287,7 +2290,10 @@ require "copy_jdk_configs.lua" %endif %changelog -* Tue Feb 05 2019 Andrew Hughes - 1:1.8.0.201.b09-0 +* Wed Feb 06 2019 Andrew John Hughes - 1:1.8.0.201.b09-2 +- Add backport of JDK-8145096 (PR3693) to fix undefined behaviour issues on newer GCCs + +* Tue Feb 05 2019 Andrew Hughes - 1:1.8.0.201.b09-1 - Update to aarch64-shenandoah-jdk8u201-b09. * Tue Feb 05 2019 Nicolas De Amicis - 1:1.8.0.192.b12-1 diff --git a/jdk8145096-pr3693-undefined_behaviour.patch b/jdk8145096-pr3693-undefined_behaviour.patch new file mode 100644 index 0000000..51aed3c --- /dev/null +++ b/jdk8145096-pr3693-undefined_behaviour.patch @@ -0,0 +1,280 @@ +# HG changeset patch +# User aph +# Date 1549014450 -3600 +# Fri Feb 01 10:47:30 2019 +0100 +# Node ID f43f77de876acfbf29c02803418d4d06d83e7dc3 +# Parent 28f68e5c6fb323c521a489cfc92e8a129379378f +8145096: Undefined behaviour in HotSpot +Summary: Fix some integer overflows +Reviewed-by: jrose, kvn, kbarrett, adinn, iklam + +diff --git openjdk.orig/hotspot/src/os/posix/vm/os_posix.cpp openjdk/hotspot/src/os/posix/vm/os_posix.cpp +--- openjdk.orig/hotspot/src/os/posix/vm/os_posix.cpp ++++ openjdk/hotspot/src/os/posix/vm/os_posix.cpp +@@ -604,7 +604,11 @@ + strncpy(buffer, "none", size); + + const struct { +- int i; ++ // NB: i is an unsigned int here because SA_RESETHAND is on some ++ // systems 0x80000000, which is implicitly unsigned. Assignining ++ // it to an int field would be an overflow in unsigned-to-signed ++ // conversion. ++ unsigned int i; + const char* s; + } flaginfo [] = { + { SA_NOCLDSTOP, "SA_NOCLDSTOP" }, +diff --git openjdk.orig/hotspot/src/share/vm/opto/addnode.cpp openjdk/hotspot/src/share/vm/opto/addnode.cpp +--- openjdk.orig/hotspot/src/share/vm/opto/addnode.cpp ++++ openjdk/hotspot/src/share/vm/opto/addnode.cpp +@@ -344,8 +344,8 @@ + const Type *AddINode::add_ring( const Type *t0, const Type *t1 ) const { + const TypeInt *r0 = t0->is_int(); // Handy access + const TypeInt *r1 = t1->is_int(); +- int lo = r0->_lo + r1->_lo; +- int hi = r0->_hi + r1->_hi; ++ int lo = java_add(r0->_lo, r1->_lo); ++ int hi = java_add(r0->_hi, r1->_hi); + if( !(r0->is_con() && r1->is_con()) ) { + // Not both constants, compute approximate result + if( (r0->_lo & r1->_lo) < 0 && lo >= 0 ) { +@@ -462,8 +462,8 @@ + const Type *AddLNode::add_ring( const Type *t0, const Type *t1 ) const { + const TypeLong *r0 = t0->is_long(); // Handy access + const TypeLong *r1 = t1->is_long(); +- jlong lo = r0->_lo + r1->_lo; +- jlong hi = r0->_hi + r1->_hi; ++ jlong lo = java_add(r0->_lo, r1->_lo); ++ jlong hi = java_add(r0->_hi, r1->_hi); + if( !(r0->is_con() && r1->is_con()) ) { + // Not both constants, compute approximate result + if( (r0->_lo & r1->_lo) < 0 && lo >= 0 ) { +diff --git openjdk.orig/hotspot/src/share/vm/opto/loopTransform.cpp openjdk/hotspot/src/share/vm/opto/loopTransform.cpp +--- openjdk.orig/hotspot/src/share/vm/opto/loopTransform.cpp ++++ openjdk/hotspot/src/share/vm/opto/loopTransform.cpp +@@ -1310,8 +1310,8 @@ + limit = new (C) Opaque2Node( C, limit ); + register_new_node( limit, opaq_ctrl ); + } +- if (stride_con > 0 && ((limit_type->_lo - stride_con) < limit_type->_lo) || +- stride_con < 0 && ((limit_type->_hi - stride_con) > limit_type->_hi)) { ++ if (stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo) || ++ stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi)) { + // No underflow. + new_limit = new (C) SubINode(limit, stride); + } else { +diff --git openjdk.orig/hotspot/src/share/vm/opto/mulnode.cpp openjdk/hotspot/src/share/vm/opto/mulnode.cpp +--- openjdk.orig/hotspot/src/share/vm/opto/mulnode.cpp ++++ openjdk/hotspot/src/share/vm/opto/mulnode.cpp +@@ -244,13 +244,13 @@ + double d = (double)hi1; + + // Compute all endpoints & check for overflow +- int32 A = lo0*lo1; ++ int32 A = java_multiply(lo0, lo1); + if( (double)A != a*c ) return TypeInt::INT; // Overflow? +- int32 B = lo0*hi1; ++ int32 B = java_multiply(lo0, hi1); + if( (double)B != a*d ) return TypeInt::INT; // Overflow? +- int32 C = hi0*lo1; ++ int32 C = java_multiply(hi0, lo1); + if( (double)C != b*c ) return TypeInt::INT; // Overflow? +- int32 D = hi0*hi1; ++ int32 D = java_multiply(hi0, hi1); + if( (double)D != b*d ) return TypeInt::INT; // Overflow? + + if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints +@@ -340,13 +340,13 @@ + double d = (double)hi1; + + // Compute all endpoints & check for overflow +- jlong A = lo0*lo1; ++ jlong A = java_multiply(lo0, lo1); + if( (double)A != a*c ) return TypeLong::LONG; // Overflow? +- jlong B = lo0*hi1; ++ jlong B = java_multiply(lo0, hi1); + if( (double)B != a*d ) return TypeLong::LONG; // Overflow? +- jlong C = hi0*lo1; ++ jlong C = java_multiply(hi0, lo1); + if( (double)C != b*c ) return TypeLong::LONG; // Overflow? +- jlong D = hi0*hi1; ++ jlong D = java_multiply(hi0, hi1); + if( (double)D != b*d ) return TypeLong::LONG; // Overflow? + + if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints +@@ -573,7 +573,8 @@ + // Masking off high bits which are always zero is useless. + const TypeLong* t1 = phase->type( in(1) )->isa_long(); + if (t1 != NULL && t1->_lo >= 0) { +- jlong t1_support = ((jlong)1 << (1 + log2_long(t1->_hi))) - 1; ++ int bit_count = log2_long(t1->_hi) + 1; ++ jlong t1_support = jlong(max_julong >> (BitsPerJavaLong - bit_count)); + if ((t1_support & con) == t1_support) + return usr; + } +@@ -801,7 +802,7 @@ + + // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits + // before shifting them away. +- const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) - CONST64(1); ++ const jlong bits_mask = jlong(max_julong >> con); + if( add1_op == Op_AndL && + phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) + return new (phase->C) LShiftLNode( add1->in(1), in(2) ); +@@ -1253,7 +1254,7 @@ + if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count + // note: mask computation below does not work for 0 shift count + // We'll be wanting the right-shift amount as a mask of that many bits +- const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) -1); ++ const jlong mask = jlong(max_julong >> con); + + // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z + // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". +diff --git openjdk.orig/hotspot/src/share/vm/opto/subnode.cpp openjdk/hotspot/src/share/vm/opto/subnode.cpp +--- openjdk.orig/hotspot/src/share/vm/opto/subnode.cpp ++++ openjdk/hotspot/src/share/vm/opto/subnode.cpp +@@ -252,8 +252,8 @@ + const Type *SubINode::sub( const Type *t1, const Type *t2 ) const { + const TypeInt *r0 = t1->is_int(); // Handy access + const TypeInt *r1 = t2->is_int(); +- int32 lo = r0->_lo - r1->_hi; +- int32 hi = r0->_hi - r1->_lo; ++ int32 lo = java_subtract(r0->_lo, r1->_hi); ++ int32 hi = java_subtract(r0->_hi, r1->_lo); + + // We next check for 32-bit overflow. + // If that happens, we just assume all integers are possible. +@@ -361,8 +361,8 @@ + const Type *SubLNode::sub( const Type *t1, const Type *t2 ) const { + const TypeLong *r0 = t1->is_long(); // Handy access + const TypeLong *r1 = t2->is_long(); +- jlong lo = r0->_lo - r1->_hi; +- jlong hi = r0->_hi - r1->_lo; ++ jlong lo = java_subtract(r0->_lo, r1->_hi); ++ jlong hi = java_subtract(r0->_hi, r1->_lo); + + // We next check for 32-bit overflow. + // If that happens, we just assume all integers are possible. +diff --git openjdk.orig/hotspot/src/share/vm/opto/type.cpp openjdk/hotspot/src/share/vm/opto/type.cpp +--- openjdk.orig/hotspot/src/share/vm/opto/type.cpp ++++ openjdk/hotspot/src/share/vm/opto/type.cpp +@@ -1329,8 +1329,8 @@ + + // The new type narrows the old type, so look for a "death march". + // See comments on PhaseTransform::saturate. +- juint nrange = _hi - _lo; +- juint orange = ohi - olo; ++ juint nrange = (juint)_hi - _lo; ++ juint orange = (juint)ohi - olo; + if (nrange < max_juint - 1 && nrange > (orange >> 1) + (SMALLINT*2)) { + // Use the new type only if the range shrinks a lot. + // We do not want the optimizer computing 2^31 point by point. +@@ -1363,7 +1363,7 @@ + //------------------------------hash------------------------------------------- + // Type-specific hashing function. + int TypeInt::hash(void) const { +- return _lo+_hi+_widen+(int)Type::Int; ++ return java_add(java_add(_lo, _hi), java_add(_widen, (int)Type::Int)); + } + + //------------------------------is_finite-------------------------------------- +@@ -1544,7 +1544,7 @@ + // If neither endpoint is extremal yet, push out the endpoint + // which is closer to its respective limit. + if (_lo >= 0 || // easy common case +- (julong)(_lo - min) >= (julong)(max - _hi)) { ++ ((julong)_lo - min) >= ((julong)max - _hi)) { + // Try to widen to an unsigned range type of 32/63 bits: + if (max >= max_juint && _hi < max_juint) + return make(_lo, max_juint, WidenMax); +@@ -2314,7 +2314,7 @@ + //------------------------------hash------------------------------------------- + // Type-specific hashing function. + int TypePtr::hash(void) const { +- return _ptr + _offset; ++ return java_add(_ptr, _offset); + } + + //------------------------------dump2------------------------------------------ +@@ -2904,12 +2904,8 @@ + // Type-specific hashing function. + int TypeOopPtr::hash(void) const { + return +- (const_oop() ? const_oop()->hash() : 0) + +- _klass_is_exact + +- _instance_id + +- hash_speculative() + +- _inline_depth + +- TypePtr::hash(); ++ java_add(java_add(java_add(const_oop() ? const_oop()->hash() : 0, _klass_is_exact), ++ java_add(_instance_id , hash_speculative())), java_add(_inline_depth , TypePtr::hash())); + } + + //------------------------------dump2------------------------------------------ +@@ -3635,7 +3631,7 @@ + //------------------------------hash------------------------------------------- + // Type-specific hashing function. + int TypeInstPtr::hash(void) const { +- int hash = klass()->hash() + TypeOopPtr::hash(); ++ int hash = java_add(klass()->hash(), TypeOopPtr::hash()); + return hash; + } + +@@ -4530,7 +4526,7 @@ + //------------------------------hash------------------------------------------- + // Type-specific hashing function. + int TypeKlassPtr::hash(void) const { +- return klass()->hash() + TypePtr::hash(); ++ return java_add(klass()->hash(), TypePtr::hash()); + } + + //------------------------------singleton-------------------------------------- +diff --git openjdk.orig/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp openjdk/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +--- openjdk.orig/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp ++++ openjdk/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +@@ -131,7 +131,8 @@ + } + + double AdvancedThresholdPolicy::weight(Method* method) { +- return (method->rate() + 1) * ((method->invocation_count() + 1) * (method->backedge_count() + 1)); ++ return (double)(method->rate() + 1) * ++ (method->invocation_count() + 1) * (method->backedge_count() + 1); + } + + // Apply heuristics and return true if x should be compiled before y +diff --git openjdk.orig/hotspot/src/share/vm/utilities/globalDefinitions.hpp openjdk/hotspot/src/share/vm/utilities/globalDefinitions.hpp +--- openjdk.orig/hotspot/src/share/vm/utilities/globalDefinitions.hpp ++++ openjdk/hotspot/src/share/vm/utilities/globalDefinitions.hpp +@@ -1403,6 +1403,32 @@ + + #define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0])) + ++//---------------------------------------------------------------------------------------------------- ++// Sum and product which can never overflow: they wrap, just like the ++// Java operations. Note that we don't intend these to be used for ++// general-purpose arithmetic: their purpose is to emulate Java ++// operations. ++ ++// The goal of this code to avoid undefined or implementation-defined ++// behaviour. The use of an lvalue to reference cast is explicitly ++// permitted by Lvalues and rvalues [basic.lval]. [Section 3.10 Para ++// 15 in C++03] ++#define JAVA_INTEGER_OP(OP, NAME, TYPE, UNSIGNED_TYPE) \ ++inline TYPE NAME (TYPE in1, TYPE in2) { \ ++ UNSIGNED_TYPE ures = static_cast(in1); \ ++ ures OP ## = static_cast(in2); \ ++ return reinterpret_cast(ures); \ ++} ++ ++JAVA_INTEGER_OP(+, java_add, jint, juint) ++JAVA_INTEGER_OP(-, java_subtract, jint, juint) ++JAVA_INTEGER_OP(*, java_multiply, jint, juint) ++JAVA_INTEGER_OP(+, java_add, jlong, julong) ++JAVA_INTEGER_OP(-, java_subtract, jlong, julong) ++JAVA_INTEGER_OP(*, java_multiply, jlong, julong) ++ ++#undef JAVA_INTEGER_OP ++ + // Dereference vptr + // All C++ compilers that we know of have the vtbl pointer in the first + // word. If there are exceptions, this function needs to be made compiler