aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJose E. Marchesi <jose.marchesi@oracle.com>2024-02-19 20:39:48 +0100
committerJose E. Marchesi <jose.marchesi@oracle.com>2024-02-19 20:48:17 +0100
commitb86b514aace19799ea141514e16296fb63a089b3 (patch)
treed191bbb58f8dc18907d5014d7cd3689f68321672 /gas
parentb47cef7ca8a2fa55acdab367c87c1ea076aec4b2 (diff)
downloadgdb-b86b514aace19799ea141514e16296fb63a089b3.zip
gdb-b86b514aace19799ea141514e16296fb63a089b3.tar.gz
gdb-b86b514aace19799ea141514e16296fb63a089b3.tar.bz2
bpf: gas: avoid UB in pointer subtraction
The PARSE_ERROR macro in md_assemble performs pointer subtraction. If parse_expression returns NULL then the later will be part of the subtraction and therefore UB will be incurred. This patch changes md_assemble to: 1. Accommodate all invocations to parse_expression to the fact it will return NULL when a parse error occurs. 2. Avoid UB in PARSE_ERROR. Tested in bpf-unknown-none target / x86_64-linux-gnu host. gas/ChangeLog: * config/tc-bpf.c (md_assemble): Fix to take into account that parse_expression can return NULL. (PARSE_ERROR): Avoid passing invalid length to parse_error.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog6
-rw-r--r--gas/config/tc-bpf.c37
2 files changed, 31 insertions, 12 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 8be2991..3ae1d77 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2024-02-19 Jose E. Marchesi <jose.marchesi@oracle.com>
+
+ * config/tc-bpf.c (md_assemble): Fix to take into account that
+ parse_expression can return NULL.
+ (PARSE_ERROR): Avoid passing invalid length to parse_error.
+
2024-02-15 Will Hawkins <hawkinsw@obs.cr>
* testsuite/gas/bpf/indcall-1-pseudoc.d: Do not select xbpf cpu
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
index 43e098c..e23de4e 100644
--- a/gas/config/tc-bpf.c
+++ b/gas/config/tc-bpf.c
@@ -935,7 +935,7 @@ encode_insn (struct bpf_insn *insn, char *bytes,
if (immediate_overflow (imm, 32))
as_bad (_("immediate out of range, shall fit in 32 bits"));
else
- encode_int32 (insn->imm32.X_add_number, bytes + 4);
+ encode_int32 (insn->imm32.X_add_number, bytes + 4);
}
if (insn->has_disp32 && insn->disp32.X_op == O_constant)
@@ -1454,7 +1454,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
partial_match_length = 0;
errmsg = NULL;
-#define PARSE_ERROR(...) parse_error (s - str, __VA_ARGS__)
+#define PARSE_ERROR(...) parse_error (s > str ? s - str : 0, __VA_ARGS__)
while ((opcode = bpf_get_opcode (idx++)) != NULL)
{
@@ -1590,6 +1590,8 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
else if (strncmp (p, "%i32", 4) == 0
|| strncmp (p, "%I32", 4) == 0)
{
+ char *exp = NULL;
+
if (p[1] == 'I')
{
while (*s == ' ' || *s == '\t')
@@ -1601,17 +1603,20 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
}
}
- s = parse_expression (s, &insn.imm32);
- if (s == NULL)
+ exp = parse_expression (s, &insn.imm32);
+ if (exp == NULL)
{
PARSE_ERROR ("expected signed 32-bit immediate");
break;
}
+ s = exp;
insn.has_imm32 = 1;
p += 4;
}
else if (strncmp (p, "%o16", 4) == 0)
{
+ char *exp = NULL;
+
while (*s == ' ' || *s == '\t')
s += 1;
if (*s != '+' && *s != '-')
@@ -1620,46 +1625,53 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
break;
}
- s = parse_expression (s, &insn.offset16);
- if (s == NULL)
+ exp = parse_expression (s, &insn.offset16);
+ if (exp == NULL)
{
PARSE_ERROR ("expected signed 16-bit offset");
break;
}
+ s = exp;
insn.has_offset16 = 1;
p += 4;
}
else if (strncmp (p, "%d16", 4) == 0)
{
- s = parse_expression (s, &insn.disp16);
- if (s == NULL)
+ char *exp = parse_expression (s, &insn.disp16);
+
+ if (exp == NULL)
{
PARSE_ERROR ("expected signed 16-bit displacement");
break;
}
+ s = exp;
insn.has_disp16 = 1;
insn.is_relaxable = (insn.disp16.X_op != O_constant);
p += 4;
}
else if (strncmp (p, "%d32", 4) == 0)
{
- s = parse_expression (s, &insn.disp32);
- if (s == NULL)
+ char *exp = parse_expression (s, &insn.disp32);
+
+ if (exp == NULL)
{
PARSE_ERROR ("expected signed 32-bit displacement");
break;
}
+ s = exp;
insn.has_disp32 = 1;
p += 4;
}
else if (strncmp (p, "%i64", 4) == 0)
{
- s = parse_expression (s, &insn.imm64);
- if (s == NULL)
+ char *exp = parse_expression (s, &insn.imm64);
+
+ if (exp == NULL)
{
PARSE_ERROR ("expected signed 64-bit immediate");
break;
}
+ s = exp;
insn.has_imm64 = 1;
insn.size = 16;
p += 4;
@@ -1717,6 +1729,7 @@ md_assemble (char *str ATTRIBUTE_UNUSED)
{
as_bad ("%s", errmsg);
free (errmsg);
+ errmsg = NULL;
}
return;