asan: null deref in coff_write_relocs
[binutils-gdb.git] / opcodes / cgen-asm.c
index f5fde408290c2ff7e5051192de9ace2459fd762d..2aa8884ab3e029467413c9b944b1a0a3125ac8df 100644 (file)
@@ -1,6 +1,5 @@
 /* CGEN generic assembler support code.
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2022 Free Software Foundation, Inc.
 
    This file is part of libopcodes.
 
@@ -61,7 +60,7 @@ cgen_init_parse_operand (CGEN_CPU_DESC cd)
    The result is a pointer to the next entry to use.
 
    The table is scanned backwards as additions are made to the front of the
-   list and we want earlier ones to be prefered.  */
+   list and we want earlier ones to be preferred.  */
 
 static CGEN_INSN_LIST *
 hash_insn_array (CGEN_CPU_DESC cd,
@@ -157,7 +156,7 @@ build_asm_hash_table (CGEN_CPU_DESC cd)
                                    asm_hash_table, hash_entry_buf);
 
   /* Add runtime added insns.
-     Later added insns will be prefered over earlier ones.  */
+     Later added insns will be preferred over earlier ones.  */
 
   hash_entry_buf = hash_insn_list (cd, insn_table->new_entries,
                                   asm_hash_table, hash_entry_buf);
@@ -213,7 +212,7 @@ cgen_parse_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
      character of the suffix ('.') is special.  */
   if (*p)
     ++p;
-  
+
   /* Allow letters, digits, and any special characters.  */
   while (((p - start) < (int) sizeof (buf))
         && *p
@@ -268,7 +267,23 @@ cgen_parse_signed_integer (CGEN_CPU_DESC cd,
      &result, &value);
   /* FIXME: Examine `result'.  */
   if (!errmsg)
-    *valuep = value;
+    {
+      /* Handle the case where a hex value is parsed on a 64-bit host.
+        A value like 0xffffe000 is clearly intended to be a negative
+        16-bit value, but on a 64-bit host it will be parsed by gas
+        as 0x00000000ffffe000.
+
+        The shifts below are designed not to produce compile time
+        warnings on a 32-bit host.  */
+      if (sizeof (value) > 4
+         && result == CGEN_PARSE_OPERAND_RESULT_NUMBER
+         && value > 0
+         && (value & 0x80000000)
+         && ((value >> 31) == 1))
+       value |= ((bfd_vma) -1) << 31;
+
+      *valuep = value;
+    }
   return errmsg;
 }