mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-20 01:50:24 +08:00
aarch64: Don't assert on long sysreg names
This patch fixes an assertion failure on long system register operands in the AArch64 backend. See the new testcase for an input which reproduces the issue. gas/ChangeLog: * 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. include/ChangeLog: * opcode/aarch64.h (AARCH64_MAX_SYSREG_NAME_LEN): New.
This commit is contained in:
@ -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>
|
2020-08-10 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (parse_sys_reg): Call to
|
* config/tc-aarch64.c (parse_sys_reg): Call to
|
||||||
|
@ -4100,17 +4100,21 @@ parse_sys_reg (char **str, struct hash_control *sys_regs,
|
|||||||
uint32_t* flags)
|
uint32_t* flags)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
char buf[32];
|
char buf[AARCH64_MAX_SYSREG_NAME_LEN];
|
||||||
const aarch64_sys_reg *o;
|
const aarch64_sys_reg *o;
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
||||||
if (p < buf + 31)
|
if (p < buf + (sizeof (buf) - 1))
|
||||||
*p++ = TOLOWER (*q);
|
*p++ = TOLOWER (*q);
|
||||||
*p = '\0';
|
*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);
|
o = hash_find (sys_regs, buf);
|
||||||
if (!o)
|
if (!o)
|
||||||
@ -4161,15 +4165,21 @@ static const aarch64_sys_ins_reg *
|
|||||||
parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
|
parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
|
||||||
{
|
{
|
||||||
char *p, *q;
|
char *p, *q;
|
||||||
char buf[32];
|
char buf[AARCH64_MAX_SYSREG_NAME_LEN];
|
||||||
const aarch64_sys_ins_reg *o;
|
const aarch64_sys_ins_reg *o;
|
||||||
|
|
||||||
p = buf;
|
p = buf;
|
||||||
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
for (q = *str; ISALNUM (*q) || *q == '_'; q++)
|
||||||
if (p < buf + 31)
|
if (p < buf + (sizeof (buf) - 1))
|
||||||
*p++ = TOLOWER (*q);
|
*p++ = TOLOWER (*q);
|
||||||
*p = '\0';
|
*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);
|
o = hash_find (sys_ins_regs, buf);
|
||||||
if (!o)
|
if (!o)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -8620,6 +8630,13 @@ checked_hash_insert (struct hash_control *table, const char *key, void *value)
|
|||||||
printf ("Internal Error: Can't hash %s\n", key);
|
printf ("Internal Error: Can't hash %s\n", key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
fill_instruction_hash_table (void)
|
fill_instruction_hash_table (void)
|
||||||
{
|
{
|
||||||
@ -8694,36 +8711,36 @@ md_begin (void)
|
|||||||
fill_instruction_hash_table ();
|
fill_instruction_hash_table ();
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs[i].name != NULL; ++i)
|
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));
|
(void *) (aarch64_sys_regs + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_pstatefields[i].name != NULL; ++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,
|
aarch64_pstatefields[i].name,
|
||||||
(void *) (aarch64_pstatefields + i));
|
(void *) (aarch64_pstatefields + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs_ic[i].name != NULL; 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,
|
aarch64_sys_regs_ic[i].name,
|
||||||
(void *) (aarch64_sys_regs_ic + i));
|
(void *) (aarch64_sys_regs_ic + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs_dc[i].name != NULL; 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,
|
aarch64_sys_regs_dc[i].name,
|
||||||
(void *) (aarch64_sys_regs_dc + i));
|
(void *) (aarch64_sys_regs_dc + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs_at[i].name != NULL; 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,
|
aarch64_sys_regs_at[i].name,
|
||||||
(void *) (aarch64_sys_regs_at + i));
|
(void *) (aarch64_sys_regs_at + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs_tlbi[i].name != NULL; 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,
|
aarch64_sys_regs_tlbi[i].name,
|
||||||
(void *) (aarch64_sys_regs_tlbi + i));
|
(void *) (aarch64_sys_regs_tlbi + i));
|
||||||
|
|
||||||
for (i = 0; aarch64_sys_regs_sr[i].name != NULL; 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,
|
aarch64_sys_regs_sr[i].name,
|
||||||
(void *) (aarch64_sys_regs_sr + i));
|
(void *) (aarch64_sys_regs_sr + i));
|
||||||
|
|
||||||
|
3
gas/testsuite/gas/aarch64/invalid-sysreg-assert.d
Normal file
3
gas/testsuite/gas/aarch64/invalid-sysreg-assert.d
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#name: don't assert on long system register
|
||||||
|
#source: invalid-sysreg-assert.s
|
||||||
|
#error_output: invalid-sysreg-assert.l
|
2
gas/testsuite/gas/aarch64/invalid-sysreg-assert.l
Normal file
2
gas/testsuite/gas/aarch64/invalid-sysreg-assert.l
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[^:]*: Assembler messages:
|
||||||
|
.*: Error: unknown or missing system register name at operand 1 -- `msr 00000000000000000000000000000000'
|
2
gas/testsuite/gas/aarch64/invalid-sysreg-assert.s
Normal file
2
gas/testsuite/gas/aarch64/invalid-sysreg-assert.s
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// This input caused an assertion failure in parse_sys_reg.
|
||||||
|
msr 00000000000000000000000000000000
|
@ -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>
|
2020-08-10 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
|
||||||
|
|
||||||
* opcode/aarch64.h (aarch64_sys_reg_deprecated_p): Functions
|
* opcode/aarch64.h (aarch64_sys_reg_deprecated_p): Functions
|
||||||
|
@ -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_prfops [32];
|
||||||
extern const struct aarch64_name_value_pair aarch64_hint_options [];
|
extern const struct aarch64_name_value_pair aarch64_hint_options [];
|
||||||
|
|
||||||
|
#define AARCH64_MAX_SYSREG_NAME_LEN 32
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char * name;
|
const char * name;
|
||||||
|
Reference in New Issue
Block a user