[PATCH] Arm: parse_neon_type() weaknesses

Jan Beulich jbeulich@suse.com
Fri Aug 1 13:40:50 GMT 2025
The custom parsing done there and in one of its callers allowed various
bogus constructs to be accepted. Insist on a non-zero leading digit when
parsing numbers, don't lose upper bits, and insist on proper separation
of operands.
---
While it would be nice to avoid the double errors on many of the lines,
first_error() doesn't really lend itself for use here, as diagnostic
arguments can't be recorded that way.

--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -1474,7 +1474,7 @@ parse_neon_type (struct neon_type *type,
   while (type->elems < NEON_MAX_TYPE_ELS)
     {
       enum neon_el_type thistype = NT_untyped;
-      unsigned thissize = -1u;
+      unsigned long thissize = -1ul;
 
       if (*ptr != '.')
 	break;
@@ -1505,14 +1505,17 @@ parse_neon_type (struct neon_type *type,
 	      return FAIL;
 	    }
 	  ptr += 1;
+	  if (!ISDIGIT (*ptr) || *ptr == '0')
+	    goto unexpected;
 	  thissize = strtoul (ptr, &ptr, 10);
 	  if (thissize != 16)
 	    {
-	      as_bad (_("bad size %d in type specifier"), thissize);
+	      as_bad (_("bad size %lu in type specifier"), thissize);
 	      return FAIL;
 	    }
 	  goto done;
 	default:
+	unexpected:
 	  as_bad (_("unexpected character `%c' in type specifier"), *ptr);
 	  return FAIL;
 	}
@@ -1525,12 +1528,14 @@ parse_neon_type (struct neon_type *type,
       else
 	{
 	parsesize:
+	  if (!ISDIGIT (*ptr) || *ptr == '0')
+	    goto unexpected;
 	  thissize = strtoul (ptr, &ptr, 10);
 
 	  if (thissize != 8 && thissize != 16 && thissize != 32
 	      && thissize != 64)
 	    {
-	      as_bad (_("bad size %d in type specifier"), thissize);
+	      as_bad (_("bad size %lu in type specifier"), thissize);
 	      return FAIL;
 	    }
 	}
@@ -22470,7 +22475,8 @@ opcode_lookup (char **str)
 	  if (parse_neon_type (&inst.vectype, str) == FAIL)
 	    return NULL;
 	}
-      else if (end[offset] != '\0' && !is_whitespace (end[offset]))
+
+      if (**str != '\0' && !is_whitespace (**str))
 	return NULL;
     }
   else
--- a/gas/testsuite/gas/arm/neon-suffix-bad.d
+++ b/gas/testsuite/gas/arm/neon-suffix-bad.d
@@ -1,3 +1,3 @@
-# name: Bad suffix for non-Neon mnemonic
+# name: Bad suffix for (non-)Neon mnemonic
 # as: -mfpu=neon
 # error_output: neon-suffix-bad.l
--- a/gas/testsuite/gas/arm/neon-suffix-bad.l
+++ b/gas/testsuite/gas/arm/neon-suffix-bad.l
@@ -7,3 +7,24 @@
 [^:]*:10: Error: invalid neon suffix for non neon instruction
 [^:]*:11: Error: invalid neon suffix for non neon instruction
 [^:]*:12: Error: invalid instruction shape -- `vcvt.f64.s32 d0,s0,#11'
+[^:]*:19: Error: unexpected character `0' .*
+#?[^:]*:19: Error: .*
+[^:]*:20: Error: unexpected character `0' .*
+#?[^:]*:20: Error: .*
+[^:]*:22: Error: unexpected character `-' .*
+#?[^:]*:22: Error: .*
+[^:]*:23: Error: bad instruction .*
+[^:]*:25: Error: bad size .*
+#?[^:]*:25: Error: .*
+[^:]*:26: Error: bad size .*
+#?[^:]*:26: Error: .*
+[^:]*:28: Error: unexpected type character `b' .*
+#?[^:]*:28: Error: .*
+[^:]*:29: Error: unexpected character ` ' .*
+#?[^:]*:29: Error: .*
+[^:]*:30: Error: .* register expected .*
+[^:]*:31: Error: unexpected character ` ' .*
+#?[^:]*:31: Error: .*
+[^:]*:32: Error: .* register expected .*
+[^:]*:34: Error: bad instruction .*
+[^:]*:35: Error: bad instruction .*
--- a/gas/testsuite/gas/arm/neon-suffix-bad.s
+++ b/gas/testsuite/gas/arm/neon-suffix-bad.s
@@ -11,3 +11,25 @@ faddd.f32 d0, d0, d0
 faddd.f64 d0, d0, d0
 vcvt.f64.s32 d0, s0, #11
 
+	.arm
+	.arch armv8.6-a
+	.arch_extension simd
+	vcvt.bf16.f32	d0, q0		@ good, for reference
+
+	vcvt.bf016.f32	d0, q0
+	vcvt.bf16.f032	d0, q0
+
+	vcvt.bf-4294967280.f32	d0, q0
+	vcvt.bf16.f-4294967264	d0, q0
+
+	vcvt.bf4294967312.f32	d0, q0
+	vcvt.bf16.f4294967328	d0, q0
+
+	vcvt.b f16.f32	d0, q0
+	vcvt.bf 16.f32	d0, q0
+	vcvt.bf16 .f32	d0, q0
+	vcvt.bf16. f32	d0, q0
+	vcvt.bf16.f 32	d0, q0
+
+	vcvt.bf16.f32d0, q0
+	vcvt.bf16.fd0, q0


More information about the Binutils mailing list