Fix segfault processing nios2 pseudo-instructions with too few arguments.
authorSandra Loosemore <sandra@codesourcery.com>
Tue, 17 Oct 2017 03:45:55 +0000 (20:45 -0700)
committerSandra Loosemore <sandra@codesourcery.com>
Tue, 17 Oct 2017 03:45:55 +0000 (20:45 -0700)
2017-10-16  Sandra Loosemore  <sandra@codesourcery.com>
    Henry Wong  <henry@stuffedcow.net>

gas/
* config/tc-nios2.c (nios2_translate_pseudo_insn): Check for
correct number of arguments.
(md_assemble): Handle failure of nios2_translate_pseudo_insn.
* testsuite/gas/nios2/illegal_pseudoinst.l: New file.
* testsuite/gas/nios2/illegal_pseudoinst.s: New file.
* testsuite/gas/nios2/nios2.exp: Add illegal_pseudoinst test.

gas/ChangeLog
gas/config/tc-nios2.c
gas/testsuite/gas/nios2/illegal_pseudoinst.l [new file with mode: 0644]
gas/testsuite/gas/nios2/illegal_pseudoinst.s [new file with mode: 0644]
gas/testsuite/gas/nios2/nios2.exp

index b8a8ce1..49b25d5 100644 (file)
@@ -1,3 +1,13 @@
+2017-10-16  Sandra Loosemore  <sandra@codesourcery.com>
+           Henry Wong  <henry@stuffedcow.net>
+
+       * config/tc-nios2.c (nios2_translate_pseudo_insn): Check for
+       correct number of arguments.
+       (md_assemble): Handle failure of nios2_translate_pseudo_insn.
+       * testsuite/gas/nios2/illegal_pseudoinst.l: New file.
+       * testsuite/gas/nios2/illegal_pseudoinst.s: New file.
+       * testsuite/gas/nios2/nios2.exp: Add illegal_pseudoinst test.
+
 2017-10-12  James Bowman  <james.bowman@ftdichip.com>
 
        * config/tc-ft32.c (md_assemble): Replace FT32_FLD_K8 with
index 4ac3eaa..372d550 100644 (file)
@@ -3244,16 +3244,29 @@ static nios2_ps_insn_infoS*
 nios2_translate_pseudo_insn (nios2_insn_infoS *insn)
 {
 
+  const struct nios2_opcode *op = insn->insn_nios2_opcode;
   nios2_ps_insn_infoS *ps_insn;
+  unsigned int tokidx, ntok;
 
   /* Find which real insn the pseudo-op translates to and
      switch the insn_info ptr to point to it.  */
-  ps_insn = nios2_ps_lookup (insn->insn_nios2_opcode->name);
+  ps_insn = nios2_ps_lookup (op->name);
 
   if (ps_insn != NULL)
     {
       insn->insn_nios2_opcode = nios2_opcode_lookup (ps_insn->insn);
       insn->insn_tokens[0] = insn->insn_nios2_opcode->name;
+      
+      /* Make sure there are enough arguments.  */
+      ntok = ((op->pinfo & NIOS2_INSN_OPTARG)
+             ? op->num_args - 1 : op->num_args);
+      for (tokidx = 1; tokidx <= ntok; tokidx++)
+       if (insn->insn_tokens[tokidx] == NULL)
+         {
+           as_bad ("missing argument");
+           return NULL;
+         }
+
       /* Modify the args so they work with the real insn.  */
       ps_insn->arg_modifer_func ((char **) insn->insn_tokens,
                                 ps_insn->arg_modifier, ps_insn->num,
@@ -3684,6 +3697,7 @@ md_assemble (char *op_str)
   unsigned long saved_pinfo = 0;
   nios2_insn_infoS thisinsn;
   nios2_insn_infoS *insn = &thisinsn;
+  bfd_boolean ps_error = FALSE;
 
   /* Make sure we are aligned on an appropriate boundary.  */
   if (nios2_current_align < nios2_min_align)
@@ -3730,35 +3744,45 @@ md_assemble (char *op_str)
         with its real equivalent, and then continue.  */
       if ((insn->insn_nios2_opcode->pinfo & NIOS2_INSN_MACRO)
          == NIOS2_INSN_MACRO)
-       ps_insn = nios2_translate_pseudo_insn (insn);
-
-      /* Assemble the parsed arguments into the instruction word.  */
-      nios2_assemble_args (insn);
-
-      /* Handle relaxation and other transformations.  */
-      if (nios2_as_options.relax != relax_none
-         && !nios2_as_options.noat
-         && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_UBRANCH)
-       output_ubranch (insn);
-      else if (nios2_as_options.relax != relax_none
-              && !nios2_as_options.noat
-              && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CBRANCH)
-       output_cbranch (insn);
-      else if (nios2_as_options.relax == relax_all
-              && !nios2_as_options.noat
-              && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CALL
-              && insn->insn_reloc
-              && ((insn->insn_reloc->reloc_type
-                   == BFD_RELOC_NIOS2_CALL26)
-                  || (insn->insn_reloc->reloc_type
-                      == BFD_RELOC_NIOS2_CALL26_NOAT)))
-       output_call (insn);
-      else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
-       output_movia (insn);
-      else
-       output_insn (insn);
-      if (ps_insn)
-       nios2_cleanup_pseudo_insn (insn, ps_insn);
+       {
+         ps_insn = nios2_translate_pseudo_insn (insn);
+         if (!ps_insn)
+           ps_error = TRUE;
+       }
+
+      /* If we found invalid pseudo-instruction syntax, the error's already
+        been diagnosed in nios2_translate_pseudo_insn, so skip
+        remaining processing.  */
+      if (!ps_error)
+       {
+         /* Assemble the parsed arguments into the instruction word.  */
+         nios2_assemble_args (insn);
+
+         /* Handle relaxation and other transformations.  */
+         if (nios2_as_options.relax != relax_none
+             && !nios2_as_options.noat
+             && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_UBRANCH)
+           output_ubranch (insn);
+         else if (nios2_as_options.relax != relax_none
+                  && !nios2_as_options.noat
+                  && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CBRANCH)
+           output_cbranch (insn);
+         else if (nios2_as_options.relax == relax_all
+                  && !nios2_as_options.noat
+                  && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CALL
+                  && insn->insn_reloc
+                  && ((insn->insn_reloc->reloc_type
+                       == BFD_RELOC_NIOS2_CALL26)
+                      || (insn->insn_reloc->reloc_type
+                          == BFD_RELOC_NIOS2_CALL26_NOAT)))
+           output_call (insn);
+         else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
+           output_movia (insn);
+         else
+           output_insn (insn);
+         if (ps_insn)
+           nios2_cleanup_pseudo_insn (insn, ps_insn);
+       }
     }
   else
     /* Unrecognised instruction - error.  */
diff --git a/gas/testsuite/gas/nios2/illegal_pseudoinst.l b/gas/testsuite/gas/nios2/illegal_pseudoinst.l
new file mode 100644 (file)
index 0000000..7d4ffdf
--- /dev/null
@@ -0,0 +1,35 @@
+.*illegal_pseudoinst.s: Assembler messages:
+.*illegal_pseudoinst.s:5: Error: missing argument
+.*illegal_pseudoinst.s:6: Error: expecting , near r2
+.*illegal_pseudoinst.s:6: Error: missing argument
+.*illegal_pseudoinst.s:7: Error: missing argument
+.*illegal_pseudoinst.s:8: Error: expecting , near r2
+.*illegal_pseudoinst.s:8: Error: missing argument
+.*illegal_pseudoinst.s:9: Error: missing argument
+.*illegal_pseudoinst.s:10: Error: missing argument
+.*illegal_pseudoinst.s:11: Error: missing argument
+.*illegal_pseudoinst.s:14: Error: missing argument
+.*illegal_pseudoinst.s:15: Error: missing argument
+.*illegal_pseudoinst.s:16: Error: expecting , near r2
+.*illegal_pseudoinst.s:16: Error: missing argument
+.*illegal_pseudoinst.s:17: Error: missing argument
+.*illegal_pseudoinst.s:18: Error: missing argument
+.*illegal_pseudoinst.s:19: Error: missing argument
+.*illegal_pseudoinst.s:22: Error: missing argument
+.*illegal_pseudoinst.s:23: Error: missing argument
+.*illegal_pseudoinst.s:24: Error: missing argument
+.*illegal_pseudoinst.s:25: Error: missing argument
+.*illegal_pseudoinst.s:26: Error: missing argument
+.*illegal_pseudoinst.s:27: Error: missing argument
+.*illegal_pseudoinst.s:28: Error: missing argument
+.*illegal_pseudoinst.s:29: Error: missing argument
+.*illegal_pseudoinst.s:30: Error: missing argument
+.*illegal_pseudoinst.s:31: Error: missing argument
+.*illegal_pseudoinst.s:34: Error: missing argument
+.*illegal_pseudoinst.s:35: Error: missing argument
+.*illegal_pseudoinst.s:36: Error: unknown register 
+.*illegal_pseudoinst.s:37: Error: missing argument
+.*illegal_pseudoinst.s:38: Error: missing argument
+.*illegal_pseudoinst.s:41: Error: missing argument
+.*illegal_pseudoinst.s:42: Error: missing argument
+.*illegal_pseudoinst.s:43: Error: missing argument
diff --git a/gas/testsuite/gas/nios2/illegal_pseudoinst.s b/gas/testsuite/gas/nios2/illegal_pseudoinst.s
new file mode 100644 (file)
index 0000000..94b48cb
--- /dev/null
@@ -0,0 +1,45 @@
+# Source file used to test missing (and illegal) operands for pseudo-instructions.
+
+foo:
+# nios2_modify_arg
+       cmpgti r2, r3,
+       cmpgtui r2, r2
+       cmplei r2, r3,
+       cmpleui r2, r2
+       cmpgti ,,
+       cmplei ,
+       cmpleui
+
+# nios2_negate_arg
+       subi Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+       subi r2, r2,
+       subi r2, r2
+       subi ,,
+       subi ,
+       subi
+
+# nios2_swap_args
+       bgt r0, r2,
+       bgtu ,,
+       ble , r0,
+       bleu foo,,
+       cmpgt r2, r3,
+       cmpgtu r2,,
+       cmple , r3,
+       cmpleu ,,
+       bgtu ,
+       ble
+
+# nios2_insert_arg
+       movi  ,
+       movhi r0,
+       movui ,r2
+       movia ,
+       movi
+
+# nios2_append_arg
+       mov r0,
+       mov ,
+       mov
+
+
index 061d610..e2cd332 100644 (file)
@@ -22,6 +22,7 @@ if { [istarget nios2-*-*] } {
     run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
     
     run_list_test "illegal" ""
+    run_list_test "illegal_pseudoinst" ""
     run_list_test "warn_nobreak" ""
     run_list_test "warn_noat" ""
     run_list_test "movi" ""