public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-8254] libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584)
@ 2021-04-20  0:28 Iain Buclaw
  0 siblings, 0 replies; only message in thread
From: Iain Buclaw @ 2021-04-20  0:28 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:30b11d8d1be9c683f1517472c47a3cb69df02c4f

commit r11-8254-g30b11d8d1be9c683f1517472c47a3cb69df02c4f
Author: Iain Buclaw <ibuclaw@gdcproject.org>
Date:   Tue Apr 20 02:09:51 2021 +0200

    libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584)
    
    Instead of unsafe pointer dereferencing, use memcpy() to read encoded
    values from memory.  The function `read_encoded_value' has been updated
    to accept a ref parameter, this simplifies handling of the pointer to
    memory needing to be read.
    
    libphobos/ChangeLog:
    
            PR d/98584
            * libdruntime/gcc/deh.d (scanLSDA): Update calls to read_uleb128 and
            read_encoded_value.
            (actionTableLookup): Update calls to read_sleb128 and
            read_encoded_value_with_base.
            * libdruntime/gcc/unwind/pe.d (read_uleb128): Update signature.
            (read_sleb128): Update signature.
            (read_unaligned): New function.
            (read_encoded_value_with_base): Update signature.  Call read_unaligned
            instead of unsafe pointer dereferencing.
            (read_encoded_value): Update signature.

Diff:
---
 libphobos/libdruntime/gcc/deh.d       | 24 +++++------
 libphobos/libdruntime/gcc/unwind/pe.d | 81 +++++++++++++++++++----------------
 2 files changed, 57 insertions(+), 48 deletions(-)

diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d
index 712f5d7bc9d..eb83751c59d 100644
--- a/libphobos/libdruntime/gcc/deh.d
+++ b/libphobos/libdruntime/gcc/deh.d
@@ -547,7 +547,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
     _Unwind_Ptr LPStart = 0;
 
     if (LPStartEncoding != DW_EH_PE_omit)
-        LPStart = read_encoded_value(context, LPStartEncoding, &p);
+        LPStart = read_encoded_value(context, LPStartEncoding, p);
     else
         LPStart = Start;
 
@@ -563,14 +563,14 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
             // hardcoded OS-specific format.
             TTypeEncoding = _TTYPE_ENCODING;
         }
-        auto TTbase = read_uleb128(&p);
+        auto TTbase = read_uleb128(p);
         TType = p + TTbase;
     }
 
     // The encoding and length of the call-site table; the action table
     // immediately follows.
     ubyte CSEncoding = *p++;
-    auto CSTableSize = read_uleb128(&p);
+    auto CSTableSize = read_uleb128(p);
     const(ubyte)* actionTable = p + CSTableSize;
 
     auto TTypeBase = base_of_encoded_value(TTypeEncoding, context);
@@ -608,8 +608,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
             _uleb128_t CSLandingPad, CSAction;
             do
             {
-                CSLandingPad = read_uleb128(&p);
-                CSAction = read_uleb128(&p);
+                CSLandingPad = read_uleb128(p);
+                CSAction = read_uleb128(p);
             }
             while (--ip);
 
@@ -626,10 +626,10 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
         while (p < actionTable)
         {
             // Note that all call-site encodings are "absolute" displacements.
-            auto CSStart = read_encoded_value(null, CSEncoding, &p);
-            auto CSLen = read_encoded_value(null, CSEncoding, &p);
-            auto CSLandingPad = read_encoded_value(null, CSEncoding, &p);
-            auto CSAction = read_uleb128(&p);
+            auto CSStart = read_encoded_value(null, CSEncoding, p);
+            auto CSLen = read_encoded_value(null, CSEncoding, p);
+            auto CSLandingPad = read_encoded_value(null, CSEncoding, p);
+            auto CSAction = read_uleb128(p);
 
             // The table is sorted, so if we've passed the ip, stop.
             if (ip < Start + CSStart)
@@ -703,9 +703,9 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
     while (1)
     {
         auto ap = actionRecord;
-        auto ARFilter = read_sleb128(&ap);
+        auto ARFilter = read_sleb128(ap);
         auto apn = ap;
-        auto ARDisp = read_sleb128(&ap);
+        auto ARDisp = read_sleb128(ap);
 
         if (ARFilter == 0)
         {
@@ -725,7 +725,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
             // the ClassInfo is stored.
             const(ubyte)* tp = TType - ARFilter * encodedSize;
 
-            auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, &tp);
+            auto entry = read_encoded_value_with_base(TTypeEncoding, TTypeBase, tp);
             ClassInfo ci = cast(ClassInfo)cast(void*)(entry);
 
             // D does not have catch-all handlers, and so the following
diff --git a/libphobos/libdruntime/gcc/unwind/pe.d b/libphobos/libdruntime/gcc/unwind/pe.d
index 361ec12490f..b9b05cbc8f6 100644
--- a/libphobos/libdruntime/gcc/unwind/pe.d
+++ b/libphobos/libdruntime/gcc/unwind/pe.d
@@ -103,40 +103,37 @@ _Unwind_Ptr base_of_encoded_value(ubyte encoding, _Unwind_Context* context)
     assert(0);
 }
 
-// Read an unsigned leb128 value from P, *P is incremented past the value.
+// Read an unsigned leb128 value from P, P is incremented past the value.
 // We assume that a word is large enough to hold any value so encoded;
 // if it is smaller than a pointer on some target, pointers should not be
 // leb128 encoded on that target.
-_uleb128_t read_uleb128(const(ubyte)** p)
+_uleb128_t read_uleb128(ref const(ubyte)* p)
 {
-    auto q = *p;
     _uleb128_t result = 0;
     uint shift = 0;
 
     while (1)
     {
-        ubyte b = *q++;
+        ubyte b = *p++;
         result |= cast(_uleb128_t)(b & 0x7F) << shift;
         if ((b & 0x80) == 0)
             break;
         shift += 7;
     }
 
-    *p = q;
     return result;
 }
 
 // Similar, but read a signed leb128 value.
-_sleb128_t read_sleb128(const(ubyte)** p)
+_sleb128_t read_sleb128(ref const(ubyte)* p)
 {
-    auto q = *p;
     _sleb128_t result = 0;
     uint shift = 0;
     ubyte b = void;
 
     while (1)
     {
-        b = *q++;
+        b = *p++;
         result |= cast(_sleb128_t)(b & 0x7F) << shift;
         shift += 7;
         if ((b & 0x80) == 0)
@@ -147,69 +144,82 @@ _sleb128_t read_sleb128(const(ubyte)** p)
     if (shift < result.sizeof * 8 && (b & 0x40))
         result |= -(cast(_sleb128_t)1 << shift);
 
-    *p = q;
     return result;
 }
 
-// Load an encoded value from memory at P.  The value is returned in VAL;
-// The function returns P incremented past the value.  BASE is as given
+// Similar, but read an unaligned value of type T.
+pragma(inline, true)
+private T read_unaligned(T)(ref const(ubyte)* p)
+{
+    version (X86)         enum hasUnalignedLoads = true;
+    else version (X86_64) enum hasUnalignedLoads = true;
+    else                  enum hasUnalignedLoads = false;
+
+    static if (hasUnalignedLoads)
+    {
+        T result = *cast(T*)p;
+    }
+    else
+    {
+        import core.stdc.string : memcpy;
+        T result = void;
+        memcpy(&result, p, T.sizeof);
+    }
+    p += T.sizeof;
+    return result;
+}
+
+// Load an encoded value from memory at P.  The function returns the
+// encoded value.  P is incremented past the value.  BASE is as given
 // by base_of_encoded_value for this encoding in the appropriate context.
 _Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base,
-                                         const(ubyte)** p)
+                                         ref const(ubyte)* p)
 {
-    auto q = *p;
+    auto psave = p;
     _Unwind_Internal_Ptr result;
 
     if (encoding == DW_EH_PE_aligned)
     {
-        _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)q;
+        _Unwind_Internal_Ptr a = cast(_Unwind_Internal_Ptr)p;
         a = cast(_Unwind_Internal_Ptr)((a + (void*).sizeof - 1) & - (void*).sizeof);
         result = *cast(_Unwind_Internal_Ptr*)a;
-        q = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof);
+        p = cast(ubyte*) cast(_Unwind_Internal_Ptr)(a + (void*).sizeof);
     }
     else
     {
         switch (encoding & 0x0f)
         {
             case DW_EH_PE_uleb128:
-                result = cast(_Unwind_Internal_Ptr)read_uleb128(&q);
+                result = cast(_Unwind_Internal_Ptr)read_uleb128(p);
                 break;
 
             case DW_EH_PE_sleb128:
-                result = cast(_Unwind_Internal_Ptr)read_sleb128(&q);
+                result = cast(_Unwind_Internal_Ptr)read_sleb128(p);
                 break;
 
             case DW_EH_PE_udata2:
-                result = cast(_Unwind_Internal_Ptr) *cast(ushort*)q;
-                q += 2;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!ushort(p);
                 break;
             case DW_EH_PE_udata4:
-                result = cast(_Unwind_Internal_Ptr) *cast(uint*)q;
-                q += 4;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!uint(p);
                 break;
             case DW_EH_PE_udata8:
-                result = cast(_Unwind_Internal_Ptr) *cast(ulong*)q;
-                q += 8;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!ulong(p);
                 break;
 
             case DW_EH_PE_sdata2:
-                result = cast(_Unwind_Internal_Ptr) *cast(short*)q;
-                q += 2;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!short(p);
                 break;
             case DW_EH_PE_sdata4:
-                result = cast(_Unwind_Internal_Ptr) *cast(int*)q;
-                q += 4;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!int(p);
                 break;
             case DW_EH_PE_sdata8:
-                result = cast(_Unwind_Internal_Ptr) *cast(long*)q;
-                q += 8;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!long(p);
                 break;
 
             case DW_EH_PE_absptr:
-                if (size_t.sizeof == 8)
-                    goto case DW_EH_PE_udata8;
-                else
-                    goto case DW_EH_PE_udata4;
+                result = cast(_Unwind_Internal_Ptr)read_unaligned!(size_t)(p);
+                break;
 
             default:
                 __builtin_abort();
@@ -218,20 +228,19 @@ _Unwind_Ptr read_encoded_value_with_base(ubyte encoding, _Unwind_Ptr base,
         if (result != 0)
         {
             result += ((encoding & 0x70) == DW_EH_PE_pcrel
-                       ? cast(_Unwind_Internal_Ptr)*p : base);
+                       ? cast(_Unwind_Internal_Ptr)psave : base);
             if (encoding & DW_EH_PE_indirect)
                 result = *cast(_Unwind_Internal_Ptr*)result;
         }
     }
 
-    *p = q;
     return result;
 }
 
 // Like read_encoded_value_with_base, but get the base from the context
 // rather than providing it directly.
 _Unwind_Ptr read_encoded_value(_Unwind_Context* context, ubyte encoding,
-                               const(ubyte)** p)
+                               ref const(ubyte)* p)
 {
     auto base = base_of_encoded_value(encoding, context);
     return read_encoded_value_with_base(encoding, base, p);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-04-20  0:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-20  0:28 [gcc r11-8254] libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584) Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).