This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH][Binutils][Arm] gas: fix out of range conditional branch (PR/24991)
- From: Tamar Christina <Tamar dot Christina at arm dot com>
- To: "nickc at redhat dot com" <nickc at redhat dot com>
- Cc: "binutils at sourceware dot org" <binutils at sourceware dot org>, nd <nd at arm dot com>, Richard Earnshaw <Richard dot Earnshaw at arm dot com>, Ramana Radhakrishnan <Ramana dot Radhakrishnan at arm dot com>
- Date: Tue, 24 Sep 2019 10:16:55 +0000
- Subject: Re: [PATCH][Binutils][Arm] gas: fix out of range conditional branch (PR/24991)
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Q9ygOOVPChszpKTez2TjU449387GjadV4GWhQqI2rCI=; b=YNEcZy3bv59JO6RhY6po5pSPAYzMjrK2qPLTm5ZoIFcokSpacyKK7ABB9ULTkrbBztbRGfIOPkdYeqXc7gGt5bf5RYh1MYxhvhp3B1W2NuRVXGyk9CH5zbU+OT089oZsy7hL+lIKmxi221Q5B9mxJNN/Z5vX9sqDJ7Oy709Df9H0T75VYlvgU+1Dc3FpnOJJLkO8D0YhwE4IF9IkKXyvPXrdNSb9SjdzbVaI742Q9i3+mYowdJlpK7/ozZTrrdEjeuEOKQ4tKw8WYj+xkHSw3cn6wUNYAV2IV9bPFMhUYiFn8iaLDBm9m02767Fl0yuIWC4VWoG2SqydOLzFVK47Rw==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hWKL+d7UyfiQmtbJjNSyPEhR+uSb0rgG++X9H1+cny7zdAwUmiecHENH0iCHIpLSU6Q5S2QLX3gxwg2szJTdrk7PtFfJsTJ3lyjDvEsY0xZy2ETayMFGJfDYHX7mDCZsuUFWHyiLnLukcp0qnSefkiC3zu5SE/FUJq01/zMlNXNHF6YbESHh7+qd335s6W6eFAOTcRyC3aHqFqrLFb0l4+XnlFiuXcandylr6D8BvvoDjvL5cMjgckBjXZsk2GE3Vu10fG06IEPNZgspN6XuPVPmUZoxLaQIJXdQsjVP2sNnoRBW/tiFHX50RnNfQs21n7JN8xRJNAVXzx8V1/H0LQ==
- Original-authentication-results: spf=none (sender IP is ) smtp.mailfrom=Tamar dot Christina at arm dot com;
- References: <20190919125957.GA801@arm.com> <b76cc1f5-813b-aab8-ced8-1ea174f2d804@redhat.com>
Hi Nick,
Attached is updated patch which should address your and Andreas Comments.
2019-09-24 Tamar Christina <tamar.christina@arm.com>
PR gas/24991
* config/tc-arm.c (out_of_range_p): New.
(md_apply_fix): Use it in BFD_RELOC_THUMB_PCREL_BRANCH9,
BFD_RELOC_THUMB_PCREL_BRANCH12, BFD_RELOC_THUMB_PCREL_BRANCH20,
BFD_RELOC_THUMB_PCREL_BRANCH23, BFD_RELOC_THUMB_PCREL_BRANCH25
* testsuite/gas/arm/pr24991.d: New test.
* testsuite/gas/arm/pr24991.l: New test.
* testsuite/gas/arm/pr24991.s: New test.
Ok for master?
Thanks,
Tamar
The 09/23/2019 11:06, Nick Clifton wrote:
> Hi Tamar,
>
> Being paranoid here....
>
> > +/* Perform range checks on positive and negative overflows by checking if the
> > + VALUE given fits within the range of an BITS sized immediate. */
> > +static bfd_boolean out_of_range_p (offsetT value, bfd_vma bits)
> > +{
> > + return (value & ~((1 << bits)-1))
> > + && ((value & ~((1 << bits)-1)) != ~((1 << bits)-1));
> > +}
>
> If bits is a large number then these shifts could overflow. I would
> recommend adding a range check first. Plus you should allow for the
> fact that sizeof (bits) and sizeof (value) could be small if the code
> is compiled for a 32-bit host...
>
> Cheers
> Nick
>
>
>
--
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 32a15f65ec852bae54184ab29447f17ab84d8fec..de0510383569b0e9cb389a7a9f2d6635a7ae3543 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -106,6 +106,15 @@ enum arm_float_abi
should define CPU_DEFAULT here. */
#endif
+/* Perform range checks on positive and negative overflows by checking if the
+ VALUE given fits within the range of an BITS sized immediate. */
+static bfd_boolean out_of_range_p (offsetT value, offsetT bits)
+ {
+ gas_assert (bits < (offsetT)(sizeof (value) * 8));
+ return (value & ~((1 << bits)-1))
+ && ((value & ~((1 << bits)-1)) != ~((1 << bits)-1));
+}
+
#ifndef FPU_DEFAULT
# ifdef TE_LINUX
# define FPU_DEFAULT FPU_ARCH_FPA
@@ -28088,7 +28097,7 @@ md_apply_fix (fixS * fixP,
break;
case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */
- if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
+ if (out_of_range_p (value, 8))
as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
if (fixP->fx_done || !seg->use_rela_p)
@@ -28100,7 +28109,7 @@ md_apply_fix (fixS * fixP,
break;
case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch. */
- if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
+ if (out_of_range_p (value, 11))
as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
if (fixP->fx_done || !seg->use_rela_p)
@@ -28111,6 +28120,7 @@ md_apply_fix (fixS * fixP,
}
break;
+ /* This relocation is misnamed, it should be BRANCH21. */
case BFD_RELOC_THUMB_PCREL_BRANCH20:
if (fixP->fx_addsy
&& (S_GET_SEGMENT (fixP->fx_addsy) == seg)
@@ -28121,7 +28131,7 @@ md_apply_fix (fixS * fixP,
/* Force a relocation for a branch 20 bits wide. */
fixP->fx_done = 0;
}
- if ((value & ~0x1fffff) && ((value & ~0x0fffff) != ~0x0fffff))
+ if (out_of_range_p (value, 20))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("conditional branch out of range"));
@@ -28200,12 +28210,11 @@ md_apply_fix (fixS * fixP,
fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
#endif
- if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
+ if (out_of_range_p (value, 22))
{
if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2)))
as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
- else if ((value & ~0x1ffffff)
- && ((value & ~0x1ffffff) != ~0x1ffffff))
+ else if (out_of_range_p (value, 24))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Thumb2 branch out of range"));
}
@@ -28216,7 +28225,7 @@ md_apply_fix (fixS * fixP,
break;
case BFD_RELOC_THUMB_PCREL_BRANCH25:
- if ((value & ~0x0ffffff) && ((value & ~0x0ffffff) != ~0x0ffffff))
+ if (out_of_range_p (value, 24))
as_bad_where (fixP->fx_file, fixP->fx_line, BAD_RANGE);
if (fixP->fx_done || !seg->use_rela_p)
diff --git a/gas/testsuite/gas/arm/pr24991.d b/gas/testsuite/gas/arm/pr24991.d
new file mode 100644
index 0000000000000000000000000000000000000000..2acca2d656ccfa9233dcdf12a35633a642d41fbe
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr24991.d
@@ -0,0 +1,4 @@
+#as: -march=armv7-a
+#source: pr24991.s
+#error_output: pr24991.l
+
diff --git a/gas/testsuite/gas/arm/pr24991.l b/gas/testsuite/gas/arm/pr24991.l
new file mode 100644
index 0000000000000000000000000000000000000000..4fc58751c8dfd866f5dc6e361434b0210c807e85
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr24991.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*:4: Error: conditional branch out of range
diff --git a/gas/testsuite/gas/arm/pr24991.s b/gas/testsuite/gas/arm/pr24991.s
new file mode 100644
index 0000000000000000000000000000000000000000..27f8daff1c81bc31dd5630f9dcff5c664d8e845f
--- /dev/null
+++ b/gas/testsuite/gas/arm/pr24991.s
@@ -0,0 +1,5 @@
+ .arch armv7-a
+ .syntax unified
+ .thumb
+ beq .+ 0x124f80
+