From patchwork Tue Jul 7 01:12:45 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 138628 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 008274BA2E31 for ; Tue, 7 Jul 2026 01:13:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 008274BA2E31 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=bPNfoHDP X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by sourceware.org (Postfix) with ESMTPS id BF0B34BA2E13 for ; Tue, 7 Jul 2026 01:12:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BF0B34BA2E13 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BF0B34BA2E13 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::530 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783386769; cv=none; b=c9hMbJ/eErpgvsllEc82pCXsyvhv8qo5lWZuP121steub2IeQ6JB5fzu2x6jCw1Ax0lUenImtieIp7Q5K7DNQjKb1KOcWNt2w37l0t2qVx/C7dP5B+uoZhsl5YaJZc4Z7P2A767/k/kuadKJhtcFHmZ4Q7N/pwIZTEHN2rgQjB8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783386769; c=relaxed/simple; bh=lrxYBOOkqIiArpxXtBHXMvs8JKJqU81QiDkAAPY9b4k=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=UoimJBewsIOUqmqKNe7aUkQrRB3C9UhMC5spxR5YiDohwULNdh7CyvISfUodMakFJ4hYkIveSx66wckDxBxpnA+BWORjo6ANK2mInhWskK+nXLzcDOz7fvzonwRORkEomQvm4leGe0GoEzHn0InPbdy6iwRUSi/Z37ZsUbttkXw= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20251104 header.b=bPNfoHDP DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BF0B34BA2E13 Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-c96b08cdd1cso2590960a12.0 for ; Mon, 06 Jul 2026 18:12:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783386769; x=1783991569; darn=sourceware.org; h=content-disposition:mime-version:message-id:subject:to:from:date :from:to:cc:subject:date:message-id:reply-to; bh=0n4aa5wx99tdUKXJ6HT6lPOwg3/1o/QkVWGxx5J0sy8=; b=bPNfoHDPDKB9XMoLr+fVAxhUoDWW/gc5Ahi8ceQ6L0awNuYg53+BTTV/W2detURRYO VRi5JDcYCxc9A4lZ6fdI5DLK0R5MzPK7v9LCheb3D5BpICpm+eHyQf/FOmQcQTTlXBYw a3EYgHO8N9Jyqm2dpKelu3qxXJw3PKUwVf19QKYJWGNovATn/8/cTVGIXYi7FMZ9Vjal ZNrmGcuJS1HzLnXU1D7bD3nWT6CbENZdLpb1CrjN4jwvSUGCjdYmHUHL49/BhXPbGdr1 fpsKY503106y2+aSymULwZ3IjDnpVjhlriJog8SWSGXJ2m7xnWImLm2QypTXWYa3yEwr aWfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783386769; x=1783991569; h=content-disposition:mime-version:message-id:subject:to:from:date :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=0n4aa5wx99tdUKXJ6HT6lPOwg3/1o/QkVWGxx5J0sy8=; b=Mxpk/O6csN/XB3WsH5J8lcwgtaXjny+ujdpBbX2bYispWcqtBpnZkpI49ZeoKl1FWR 83HHXzmWSvnXGqZgbKD0103WxpkejTKgEb6nSk+5PpCXJjagvxyI2fLboX62RZIEQ4dh OnXiJK76hSpvkBoUudQsVAqZLNoXqJSkcpzLQaUkbHvARph7b7pCFvW9HJM2jJKgyVvL xa8To92ZfSzp2SzVQYESjbEErNq5yOnTLT84wAUYA+cZuUPYRa0lLAI9dGIc1c7A9RUD 136IDpOwJGxE0BA1PayNGFBc/8njtaO9M7iMjnNqjn/vyojbmBd6uKRh8rZRa59xBoG4 piqQ== X-Gm-Message-State: AOJu0YyJJNadTaCum9v30XICDIMicqBNH7jBaBSVUAFTgOOddh3ELtKp KZL3Hnp13bktZ2Hthzln0RpedXXwW+T+CshO5GwBhjgoZJi5LPlICmGuUhSgcw== X-Gm-Gg: AfdE7cl7uZKF32u1SZGMkgX0fE72NBkKYy3prn7pAT+iSI8hoalJtriJZrbpbF202iZ uloU1EJeToP7fY29ELc7Fp7j1mBPWprp/VIzVS4AslbmvWGyRDk82bPUjTubuaBm3hcFQqegHgy befhtf+AxMTHFaMALS5m5mmtJRI5Hcm622yCtx5qBgFN1W7CQ4DQoufEUweE9Qp1HBFM4izXwD2 DYDdlz4z6Yp+lGV+ug1sOiJ95KeuF64bfen6VPLtvQm8zf/j4cW8WX0T5rBi7AeNZ3S3z942iKb h1ivWeFA+INkieOyL4C9NwscqDiiLNcGAly/6IdiyKPAa9QxmIVz9IzB0KDr8LipMf7HBH8i/rj is4A+tHISBKgejPy9ZtudRQh+RctO580N4chpwULDx10PrAPM+PB7Dz905y2G8zZvt4rEhTdfPk HCyPgPOk6ScsqVLh6pECL7Mg== X-Received: by 2002:a05:6a21:3d84:b0:3bf:aff8:f572 with SMTP id adf61e73a8af0-3c08ee92e86mr2720607637.32.1783386768549; Mon, 06 Jul 2026 18:12:48 -0700 (PDT) Received: from squeak.grove.modra.org ([58.96.106.158]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3117483dec6sm1958094eec.11.2026.07.06.18.12.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Jul 2026 18:12:48 -0700 (PDT) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 1E2F31141AFD; Tue, 07 Jul 2026 10:42:45 +0930 (ACST) Date: Tue, 7 Jul 2026 10:42:45 +0930 From: Alan Modra To: binutils@sourceware.org Subject: alpha, rl78, rx: UB in reloc handling Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-3029.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org This patch avoids undefined behaviour and divide by zero exceptions in some relocation processing. In most cases, unsigned arithmetic is used which has defined overflow characteristics. Arithmetic right shift, division, and modulo operations have more special cases. See the explanation in commit 30200464e9dd. * coff-alpha.c (alpha_ecoff_get_relocated_section_contents): Avoid UB in RSHIFT reloc. (alpha_relocate_section): Likewise. * elf32-rl78.c (rl78_compute_complex_reloc): Avoid UB in reloc arithmetic. * elf32-rx.c (rx_elf_relocate_section): Likewise. (rx_offset_for_reloc): Likewise. diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 35677e9a933..f0823cdcaa9 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -1128,7 +1128,10 @@ alpha_ecoff_get_relocated_section_contents (bfd *abfd, break; } - stack[tos - 1] >>= relocation; + if (relocation >= 64) + stack[tos - 1] = 0; + else + stack[tos - 1] >>= relocation; } break; @@ -1755,7 +1758,10 @@ alpha_relocate_section (bfd *output_bfd, r = bfd_reloc_notsupported; break; } - stack[tos - 1] >>= addend; + if (addend >= 64) + stack[tos - 1] = 0; + else + stack[tos - 1] >>= addend; break; } } diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index 2b782c1463a..e9e047fcca7 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -442,14 +442,14 @@ rl78_compute_complex_reloc (unsigned long r_type, case R_RL78_OPneg: tmp1 = rl78_stack_pop (&status); - tmp1 = - tmp1; + tmp1 = -(uint32_t) tmp1; rl78_stack_push (tmp1, &status); break; case R_RL78_OPadd: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - tmp1 += tmp2; + tmp1 += (uint32_t) tmp2; rl78_stack_push (tmp1, &status); break; @@ -458,41 +458,51 @@ rl78_compute_complex_reloc (unsigned long r_type, then B, then OPSUB. So the first op we pop is B, not A. */ tmp2 = rl78_stack_pop (&status); /* B */ tmp1 = rl78_stack_pop (&status); /* A */ - tmp1 -= tmp2; /* A - B */ + tmp1 -= (uint32_t) tmp2; /* A - B */ rl78_stack_push (tmp1, &status); break; case R_RL78_OPmul: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - tmp1 *= tmp2; + tmp1 *= (uint32_t) tmp2; rl78_stack_push (tmp1, &status); break; case R_RL78_OPdiv: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - if (tmp2 != 0) - tmp1 /= tmp2; - else + if (tmp2 == 0) { tmp1 = 0; status = bfd_reloc_overflow; } + else if (tmp2 == 1) + ; + else if (tmp2 == -1) + tmp1 = -(uint32_t) tmp1; + else + tmp1 /= tmp2; rl78_stack_push (tmp1, &status); break; case R_RL78_OPshla: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - tmp1 <<= tmp2; + if ((uint32_t) tmp2 >= 32) + tmp1 = 0; + else + tmp1 = (uint32_t) tmp1 << tmp2; rl78_stack_push (tmp1, &status); break; case R_RL78_OPshra: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - tmp1 >>= tmp2; + if ((uint32_t) tmp2 >= 31) + tmp1 = tmp1 < 0 ? -1 : 1; + else + tmp1 >>= tmp2; rl78_stack_push (tmp1, &status); break; @@ -534,13 +544,15 @@ rl78_compute_complex_reloc (unsigned long r_type, case R_RL78_OPmod: tmp2 = rl78_stack_pop (&status); tmp1 = rl78_stack_pop (&status); - if (tmp2 != 0) - tmp1 %= tmp2; - else + if (tmp2 == 0) { tmp1 = 0; status = bfd_reloc_overflow; } + else if (tmp2 == 1 || tmp2 == -1) + tmp1 = 0; + else + tmp1 %= tmp2; rl78_stack_push (tmp1, &status); break; } diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c index 1421e443e51..68eb99fd392 100644 --- a/bfd/elf32-rx.c +++ b/bfd/elf32-rx.c @@ -1308,7 +1308,7 @@ rx_elf_relocate_section case R_RX_OPneg: { - int32_t tmp; + uint32_t tmp; saw_subtract = true; RX_STACK_POP (tmp); @@ -1319,7 +1319,7 @@ rx_elf_relocate_section case R_RX_OPadd: { - int32_t tmp1, tmp2; + uint32_t tmp1, tmp2; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); @@ -1330,7 +1330,7 @@ rx_elf_relocate_section case R_RX_OPsub: { - int32_t tmp1, tmp2; + uint32_t tmp1, tmp2; saw_subtract = true; RX_STACK_POP (tmp1); @@ -1342,7 +1342,7 @@ rx_elf_relocate_section case R_RX_OPmul: { - int32_t tmp1, tmp2; + uint32_t tmp1, tmp2; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); @@ -1357,29 +1357,46 @@ rx_elf_relocate_section RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 /= tmp2; + if (tmp2 == 0) + { + tmp1 = 0; + r = bfd_reloc_overflow; + } + else if (tmp2 == 1) + ; + else if (tmp2 == -1) + tmp1 = - (uint32_t) tmp1; + else + tmp1 /= tmp2; RX_STACK_PUSH (tmp1); } break; case R_RX_OPshla: { - int32_t tmp1, tmp2; + uint32_t tmp1, tmp2; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 <<= tmp2; + if (tmp2 >= 32) + tmp1 = 0; + else + tmp1 <<= tmp2; RX_STACK_PUSH (tmp1); } break; case R_RX_OPshra: { - int32_t tmp1, tmp2; + int32_t tmp1; + uint32_t tmp2; RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 >>= tmp2; + if (tmp2 >= 31) + tmp1 = tmp1 < 0 ? -1 : 1; + else + tmp1 >>= tmp2; RX_STACK_PUSH (tmp1); } break; @@ -1441,7 +1458,15 @@ rx_elf_relocate_section RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 %= tmp2; + if (tmp2 == 0) + { + tmp1 = 0; + r = bfd_reloc_overflow; + } + else if (tmp2 == 1 || tmp2 == -1) + tmp1 = 0; + else + tmp1 %= tmp2; RX_STACK_PUSH (tmp1); } break; @@ -1853,49 +1878,62 @@ rx_offset_for_reloc (bfd * abfd, case R_RX_OPneg: RX_STACK_POP (tmp1); - tmp1 = - tmp1; + tmp1 = - (uint32_t) tmp1; RX_STACK_PUSH (tmp1); break; case R_RX_OPadd: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 += tmp2; + tmp1 += (uint32_t) tmp2; RX_STACK_PUSH (tmp1); break; case R_RX_OPsub: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp2 -= tmp1; + tmp2 -= (uint32_t) tmp1; RX_STACK_PUSH (tmp2); break; case R_RX_OPmul: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 *= tmp2; + tmp1 *= (uint32_t) tmp2; RX_STACK_PUSH (tmp1); break; case R_RX_OPdiv: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 /= tmp2; + if (tmp2 == 0) + tmp1 = 0; + else if (tmp2 == 1) + ; + else if (tmp2 == -1) + tmp1 = - (uint32_t) tmp1; + else + tmp1 /= tmp2; RX_STACK_PUSH (tmp1); break; case R_RX_OPshla: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 <<= tmp2; + if ((uint32_t) tmp2 >= 32) + tmp1 = 0; + else + tmp1 = (uint32_t) tmp1 << tmp2; RX_STACK_PUSH (tmp1); break; case R_RX_OPshra: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 >>= tmp2; + if ((uint32_t) tmp2 >= 31) + tmp1 = tmp1 < 0 ? -1 : 1; + else + tmp1 >>= tmp2; RX_STACK_PUSH (tmp1); break; @@ -1937,7 +1975,12 @@ rx_offset_for_reloc (bfd * abfd, case R_RX_OPmod: RX_STACK_POP (tmp1); RX_STACK_POP (tmp2); - tmp1 %= tmp2; + if (tmp2 == 0) + tmp1 = 0; + else if (tmp2 == -1 || tmp2 == 1) + tmp1 = 0; + else + tmp1 %= tmp2; RX_STACK_PUSH (tmp1); break;