Avoid undefined behaviour in m68hc11 md_begin
authorAlan Modra <amodra@gmail.com>
Tue, 28 Mar 2023 09:55:26 +0000 (20:25 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 28 Mar 2023 10:34:30 +0000 (21:04 +1030)
Given p = A where p is a pointer to some type and A is an array of
that type, then the expression p - 1 + 1 evokes undefined behaviour
according to the C standard.

gcc-13 -fsanitize=address,undefined complains about this, but not
where the undefined behaviour actually occurs at tc-m68hc11.c:646.
Instead you get an error: "tc-m68hc11.c:708:20: runtime error: store
to address 0x62600000016c with insufficient space for an object of
type 'int'".  Which is a lie.  There most definitely is space there.
Oh well, diagnostics are sometimes hard to get right.  The UB is easy
to avoid.

PR 30279
* config/tc-m68hc11.c (md_begin): Avoid undefined pointer
decrement.  Remove unnecessary cast.

gas/config/tc-m68hc11.c

index 7438e0dd51dadb5284d05c6aa828da6372243070..270ddf999ce10c482f6b8aa67167d01c285a0308 100644 (file)
@@ -643,7 +643,7 @@ md_begin (void)
          (int (*) (const void*, const void*)) cmp_opcode);
 
   opc = XNEWVEC (struct m68hc11_opcode_def, num_opcodes);
-  m68hc11_opcode_defs = opc--;
+  m68hc11_opcode_defs = opc;
 
   /* Insert unique names into hash table.  The M6811 instruction set
      has several identical opcode names that have different opcodes based
@@ -655,19 +655,18 @@ md_begin (void)
 
       if (strcmp (prev_name, opcodes->name))
        {
-         prev_name = (char *) opcodes->name;
-
+         prev_name = opcodes->name;
          opc++;
-         opc->format = 0;
-         opc->min_operands = 100;
-         opc->max_operands = 0;
-         opc->nb_modes = 0;
-         opc->opcode = opcodes;
-         opc->used = 0;
-         str_hash_insert (m68hc11_hash, opcodes->name, opc, 0);
+         (opc - 1)->format = 0;
+         (opc - 1)->min_operands = 100;
+         (opc - 1)->max_operands = 0;
+         (opc - 1)->nb_modes = 0;
+         (opc - 1)->opcode = opcodes;
+         (opc - 1)->used = 0;
+         str_hash_insert (m68hc11_hash, opcodes->name, opc - 1, 0);
        }
-      opc->nb_modes++;
-      opc->format |= opcodes->format;
+      (opc - 1)->nb_modes++;
+      (opc - 1)->format |= opcodes->format;
 
       /* See how many operands this opcode needs.  */
       expect = 0;
@@ -700,14 +699,13 @@ md_begin (void)
            expect++;
        }
 
-      if (expect < opc->min_operands)
-       opc->min_operands = expect;
+      if (expect < (opc - 1)->min_operands)
+       (opc - 1)->min_operands = expect;
       if (IS_CALL_SYMBOL (opcodes->format))
        expect++;
-      if (expect > opc->max_operands)
-       opc->max_operands = expect;
+      if (expect > (opc - 1)->max_operands)
+       (opc - 1)->max_operands = expect;
     }
-  opc++;
   m68hc11_nb_opcode_defs = opc - m68hc11_opcode_defs;
 
   if (flag_print_opcodes)