aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog12
-rw-r--r--gas/config/tc-aarch64.c43
-rw-r--r--gas/testsuite/gas/aarch64/invalid-sysreg-assert.d3
-rw-r--r--gas/testsuite/gas/aarch64/invalid-sysreg-assert.l2
-rw-r--r--gas/testsuite/gas/aarch64/invalid-sysreg-assert.s2
-rw-r--r--include/ChangeLog4
-rw-r--r--include/opcode/aarch64.h2
7 files changed, 55 insertions, 13 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 03628a6..07def54 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,15 @@
+2020-08-10 Alex Coplan <alex.coplan@arm.com>
+
+ * config/tc-aarch64.c (parse_sys_reg): Don't assert when parsing
+ a long system register.
+ (parse_sys_ins_reg): Likewise.
+ (sysreg_hash_insert): New.
+ (md_begin): Use sysreg_hash_insert() to ensure all system
+ registers are no longer than the maximum length at startup.
+ * testsuite/gas/aarch64/invalid-sysreg-assert.d: New test.
+ * testsuite/gas/aarch64/invalid-sysreg-assert.l: Error output.
+ * testsuite/gas/aarch64/invalid-sysreg-assert.s: Input.
+
2020-08-10 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
* config/tc-aarch64.c (parse_sys_reg): Call to
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index a46a474..fdac91e 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -4100,17 +4100,21 @@ parse_sys_reg (char **str, struct hash_control *sys_regs,
uint32_t* flags)
{
char *p, *q;
- char buf[32];
+ char buf[AARCH64_MAX_SYSREG_NAME_LEN];
const aarch64_sys_reg *o;
int value;
p = buf;
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
- if (p < buf + 31)
+ if (p < buf + (sizeof (buf) - 1))
*p++ = TOLOWER (*q);
*p = '\0';
- /* Assert that BUF be large enough. */
- gas_assert (p - buf == q - *str);
+
+ /* If the name is longer than AARCH64_MAX_SYSREG_NAME_LEN then it cannot be a
+ valid system register. This is enforced by construction of the hash
+ table. */
+ if (p - buf != q - *str)
+ return PARSE_FAIL;
o = hash_find (sys_regs, buf);
if (!o)
@@ -4161,15 +4165,21 @@ static const aarch64_sys_ins_reg *
parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
{
char *p, *q;
- char buf[32];
+ char buf[AARCH64_MAX_SYSREG_NAME_LEN];
const aarch64_sys_ins_reg *o;
p = buf;
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
- if (p < buf + 31)
+ if (p < buf + (sizeof (buf) - 1))
*p++ = TOLOWER (*q);
*p = '\0';
+ /* If the name is longer than AARCH64_MAX_SYSREG_NAME_LEN then it cannot be a
+ valid system register. This is enforced by construction of the hash
+ table. */
+ if (p - buf != q - *str)
+ return NULL;
+
o = hash_find (sys_ins_regs, buf);
if (!o)
return NULL;
@@ -8621,6 +8631,13 @@ checked_hash_insert (struct hash_control *table, const char *key, void *value)
}
static void
+sysreg_hash_insert (struct hash_control *table, const char *key, void *value)
+{
+ gas_assert (strlen (key) < AARCH64_MAX_SYSREG_NAME_LEN);
+ checked_hash_insert (table, key, value);
+}
+
+static void
fill_instruction_hash_table (void)
{
aarch64_opcode *opcode = aarch64_opcode_table;
@@ -8694,36 +8711,36 @@ md_begin (void)
fill_instruction_hash_table ();
for (i = 0; aarch64_sys_regs[i].name != NULL; ++i)
- checked_hash_insert (aarch64_sys_regs_hsh, aarch64_sys_regs[i].name,
+ sysreg_hash_insert (aarch64_sys_regs_hsh, aarch64_sys_regs[i].name,
(void *) (aarch64_sys_regs + i));
for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
- checked_hash_insert (aarch64_pstatefield_hsh,
+ sysreg_hash_insert (aarch64_pstatefield_hsh,
aarch64_pstatefields[i].name,
(void *) (aarch64_pstatefields + i));
for (i = 0; aarch64_sys_regs_ic[i].name != NULL; i++)
- checked_hash_insert (aarch64_sys_regs_ic_hsh,
+ sysreg_hash_insert (aarch64_sys_regs_ic_hsh,
aarch64_sys_regs_ic[i].name,
(void *) (aarch64_sys_regs_ic + i));
for (i = 0; aarch64_sys_regs_dc[i].name != NULL; i++)
- checked_hash_insert (aarch64_sys_regs_dc_hsh,
+ sysreg_hash_insert (aarch64_sys_regs_dc_hsh,
aarch64_sys_regs_dc[i].name,
(void *) (aarch64_sys_regs_dc + i));
for (i = 0; aarch64_sys_regs_at[i].name != NULL; i++)
- checked_hash_insert (aarch64_sys_regs_at_hsh,
+ sysreg_hash_insert (aarch64_sys_regs_at_hsh,
aarch64_sys_regs_at[i].name,
(void *) (aarch64_sys_regs_at + i));
for (i = 0; aarch64_sys_regs_tlbi[i].name != NULL; i++)
- checked_hash_insert (aarch64_sys_regs_tlbi_hsh,
+ sysreg_hash_insert (aarch64_sys_regs_tlbi_hsh,
aarch64_sys_regs_tlbi[i].name,
(void *) (aarch64_sys_regs_tlbi + i));
for (i = 0; aarch64_sys_regs_sr[i].name != NULL; i++)
- checked_hash_insert (aarch64_sys_regs_sr_hsh,
+ sysreg_hash_insert (aarch64_sys_regs_sr_hsh,
aarch64_sys_regs_sr[i].name,
(void *) (aarch64_sys_regs_sr + i));
diff --git a/gas/testsuite/gas/aarch64/invalid-sysreg-assert.d b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.d
new file mode 100644
index 0000000..a6279bb
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.d
@@ -0,0 +1,3 @@
+#name: don't assert on long system register
+#source: invalid-sysreg-assert.s
+#error_output: invalid-sysreg-assert.l
diff --git a/gas/testsuite/gas/aarch64/invalid-sysreg-assert.l b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.l
new file mode 100644
index 0000000..b604910
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.l
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+.*: Error: unknown or missing system register name at operand 1 -- `msr 00000000000000000000000000000000'
diff --git a/gas/testsuite/gas/aarch64/invalid-sysreg-assert.s b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.s
new file mode 100644
index 0000000..8b3706f
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/invalid-sysreg-assert.s
@@ -0,0 +1,2 @@
+// This input caused an assertion failure in parse_sys_reg.
+msr 00000000000000000000000000000000
diff --git a/include/ChangeLog b/include/ChangeLog
index 27f14cc..d0475de 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2020-08-10 Alex Coplan <alex.coplan@arm.com>
+
+ * opcode/aarch64.h (AARCH64_MAX_SYSREG_NAME_LEN): New.
+
2020-08-10 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
* opcode/aarch64.h (aarch64_sys_reg_deprecated_p): Functions
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 4b71f93..5122ea8 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -943,6 +943,8 @@ extern const struct aarch64_name_value_pair aarch64_barrier_options [16];
extern const struct aarch64_name_value_pair aarch64_prfops [32];
extern const struct aarch64_name_value_pair aarch64_hint_options [];
+#define AARCH64_MAX_SYSREG_NAME_LEN 32
+
typedef struct
{
const char * name;