From patchwork Tue Apr 20 00:29:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1468144 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=mBoqCLxw; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FPPgx2sjZz9vDc for ; Tue, 20 Apr 2021 10:29:15 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 430E3385803D; Tue, 20 Apr 2021 00:29:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 430E3385803D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1618878552; bh=okwIYSOdut8S3PIX5vihAtCi3s3NzXEZ2tK+mLp22MU=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=mBoqCLxwBBUpcc2g8mD61fhaCxYq4jKhzlNOi1wtoiQTXdRynpV2jXiqIvEyQ+EGe GMV884KS6TYZqX6xDYmrV3Voo6q+nfWZwkWkAmU3pwmQTVdM+rpl8LvsNQSZicfwrW PK8GZdjYtz+fXvOYlH6O1umziD2o2o/4LduCdCpQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [IPv6:2001:67c:2050::465:201]) by sourceware.org (Postfix) with ESMTPS id 8539F3858028 for ; Tue, 20 Apr 2021 00:29:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8539F3858028 Received: from smtp2.mailbox.org (smtp2.mailbox.org [80.241.60.241]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4FPPgk5jFwzQj6k; Tue, 20 Apr 2021 02:29:06 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de Received: from smtp2.mailbox.org ([80.241.60.241]) by spamfilter01.heinlein-hosting.de (spamfilter01.heinlein-hosting.de [80.241.56.115]) (amavisd-new, port 10030) with ESMTP id Zjxrd1qhr8yf; Tue, 20 Apr 2021 02:29:03 +0200 (CEST) To: gcc-patches@gcc.gnu.org Subject: [committed] libphobos: Fix SIGBUS in read_encoded_value_with_base on sparc-sun-solaris (PR98584) Date: Tue, 20 Apr 2021 02:29:02 +0200 Message-Id: <20210420002902.1132994-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-MBO-SPAM-Probability: * X-Rspamd-Score: 1.29 / 15.00 / 15.00 X-Rspamd-Queue-Id: CD50617DF X-Rspamd-UID: bece80 X-Spam-Status: No, score=-15.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hi, This patch adjusts the `read_encoded_value_with_base' function in libphobos to correctly handle unaligned loads. 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. Bootstrapped and regression tested on x86_64-linux-gnu/-m32/-mx32, with further testing done on sparc-sun-solaris2.11 to verify the target platform the PR was raised against has been fixed. Committed to mainline. Regards, Iain. --- 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. --- 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);