adding some simple provenance checks on return values
This commit is contained in:
parent
7d48d3beb1
commit
a299bad75b
File diff suppressed because one or more lines are too long
|
@ -994,6 +994,14 @@ impl Nodes {
|
|||
continue;
|
||||
}
|
||||
|
||||
if self[class.1].outputs.iter().any(|&n| {
|
||||
self[n].kind != Kind::Stre
|
||||
&& self[n].outputs.iter().any(|&n| self[n].kind != Kind::Stre)
|
||||
}) {
|
||||
new_inps.push(n);
|
||||
continue;
|
||||
}
|
||||
|
||||
cursor = self[cursor].inputs[3];
|
||||
while cursor != MEM {
|
||||
debug_assert_eq!(self[cursor].kind, Kind::Stre);
|
||||
|
@ -1799,6 +1807,7 @@ pub struct Node {
|
|||
loop_depth: Cell<LoopDepth>,
|
||||
aclass: AClassId,
|
||||
antidep: Nid,
|
||||
pos: Pos,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
|
@ -2318,9 +2327,10 @@ impl<'a> Codegen<'a> {
|
|||
self.ct.run(ret_loc, entry)
|
||||
}
|
||||
|
||||
fn new_stack(&mut self, ty: ty::Id) -> Nid {
|
||||
fn new_stack(&mut self, pos: Pos, ty: ty::Id) -> Nid {
|
||||
let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]);
|
||||
self.ci.nodes[stck].aclass = self.ci.scope.aclasses.len() as _;
|
||||
self.ci.nodes[stck].pos = pos;
|
||||
self.ci.scope.aclasses.push(AClass::new(&mut self.ci.nodes));
|
||||
stck
|
||||
}
|
||||
|
@ -2452,7 +2462,7 @@ impl<'a> Codegen<'a> {
|
|||
Loc::Reg => Some(self.ci.nodes.new_const_lit(oty, 0)),
|
||||
Loc::Stack => {
|
||||
let OptLayout { flag_ty, flag_offset, .. } = self.tys.opt_layout(ty);
|
||||
let stack = self.new_stack(oty);
|
||||
let stack = self.new_stack(pos, oty);
|
||||
let offset = self.offset(stack, flag_offset);
|
||||
let value = self.ci.nodes.new_const(flag_ty, 0);
|
||||
self.store_mem(offset, flag_ty, value);
|
||||
|
@ -2464,7 +2474,7 @@ impl<'a> Codegen<'a> {
|
|||
inference!(ty, ctx, self, pos, "value", "@as(<ty>, idk)");
|
||||
|
||||
if ty.loc(self.tys) == Loc::Stack {
|
||||
Some(Value::ptr(self.new_stack(ty)).ty(ty))
|
||||
Some(Value::ptr(self.new_stack(pos, ty)).ty(ty))
|
||||
} else {
|
||||
Some(self.ci.nodes.new_const_lit(ty, 0))
|
||||
}
|
||||
|
@ -2562,6 +2572,8 @@ impl<'a> Codegen<'a> {
|
|||
&mut self.ci.nodes,
|
||||
);
|
||||
|
||||
self.ci.nodes[self.ci.ctrl.get()].pos = pos;
|
||||
|
||||
self.ci.nodes[NEVER].inputs.push(self.ci.ctrl.get());
|
||||
self.ci.nodes[self.ci.ctrl.get()].outputs.push(NEVER);
|
||||
} else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret {
|
||||
|
@ -2661,7 +2673,7 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
||||
}
|
||||
Expr::UnOp { op: TokenKind::Band, val, .. } => {
|
||||
Expr::UnOp { op: TokenKind::Band, val, pos } => {
|
||||
let ctx = Ctx { ty: ctx.ty.and_then(|ty| self.tys.base_of(ty)) };
|
||||
|
||||
let mut val = self.raw_expr_ctx(val, ctx)?;
|
||||
|
@ -2673,7 +2685,7 @@ impl<'a> Codegen<'a> {
|
|||
return Some(val);
|
||||
}
|
||||
|
||||
let stack = self.new_stack(val.ty);
|
||||
let stack = self.new_stack(pos, val.ty);
|
||||
self.store_mem(stack, val.ty, val.id);
|
||||
|
||||
Some(Value::new(stack).ty(self.tys.make_ptr(val.ty)))
|
||||
|
@ -2710,11 +2722,11 @@ impl<'a> Codegen<'a> {
|
|||
Value::NEVER
|
||||
}
|
||||
}
|
||||
Expr::BinOp { left, op: TokenKind::Decl, right, .. } => {
|
||||
Expr::BinOp { left, op: TokenKind::Decl, right, pos } => {
|
||||
let mut right = self.expr(right)?;
|
||||
|
||||
if right.ty.loc(self.tys) == Loc::Stack {
|
||||
let stck = self.new_stack(right.ty);
|
||||
let stck = self.new_stack(pos, right.ty);
|
||||
self.store_mem(stck, right.ty, right.id);
|
||||
right.id = stck;
|
||||
right.ptr = true;
|
||||
|
@ -2807,7 +2819,7 @@ impl<'a> Codegen<'a> {
|
|||
let mut rhs = rhs?;
|
||||
self.strip_var(&mut rhs);
|
||||
self.assert_ty(pos, &mut rhs, lhs.ty, "struct operand");
|
||||
let dst = self.new_stack(lhs.ty);
|
||||
let dst = self.new_stack(pos, lhs.ty);
|
||||
self.struct_op(left.pos(), op, s, dst, lhs.id, rhs.id);
|
||||
Some(Value::ptr(dst).ty(lhs.ty))
|
||||
}
|
||||
|
@ -2906,7 +2918,7 @@ impl<'a> Codegen<'a> {
|
|||
match ty.loc(self.tys) {
|
||||
Loc::Reg if mem::take(&mut val.ptr) => val.id = self.load_mem(val.id, ty),
|
||||
Loc::Stack if !val.ptr => {
|
||||
let stack = self.new_stack(ty);
|
||||
let stack = self.new_stack(pos, ty);
|
||||
self.store_mem(stack, val.ty, val.id);
|
||||
val.id = stack;
|
||||
val.ptr = true;
|
||||
|
@ -3074,7 +3086,7 @@ impl<'a> Codegen<'a> {
|
|||
let alt_value = match ty.loc(self.tys) {
|
||||
Loc::Reg => None,
|
||||
Loc::Stack => {
|
||||
let stck = self.new_stack(ty);
|
||||
let stck = self.new_stack(pos, ty);
|
||||
inps.push(stck);
|
||||
Some(Value::ptr(stck).ty(ty))
|
||||
}
|
||||
|
@ -3151,7 +3163,7 @@ impl<'a> Codegen<'a> {
|
|||
let alt_value = match sig.ret.loc(self.tys) {
|
||||
Loc::Reg => None,
|
||||
Loc::Stack => {
|
||||
let stck = self.new_stack(sig.ret);
|
||||
let stck = self.new_stack(func.pos(), sig.ret);
|
||||
inps.push(stck);
|
||||
Some(Value::ptr(stck).ty(sig.ret))
|
||||
}
|
||||
|
@ -3298,7 +3310,7 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
match sty.expand() {
|
||||
ty::Kind::Struct(s) => {
|
||||
let mem = self.new_stack(sty);
|
||||
let mem = self.new_stack(pos, sty);
|
||||
let mut offs = OffsetIter::new(s, self.tys);
|
||||
for field in fields {
|
||||
let Some((ty, offset)) = offs.next_ty(self.tys) else {
|
||||
|
@ -3352,7 +3364,7 @@ impl<'a> Codegen<'a> {
|
|||
return Value::NEVER;
|
||||
}
|
||||
|
||||
let mem = self.new_stack(aty);
|
||||
let mem = self.new_stack(pos, aty);
|
||||
|
||||
for (field, offset) in
|
||||
fields.iter().zip((0u32..).step_by(elem_size as usize))
|
||||
|
@ -3407,7 +3419,7 @@ impl<'a> Codegen<'a> {
|
|||
.into_iter(self.tys)
|
||||
.map(|(f, o)| (f.ty, o))
|
||||
.collect::<Vec<_>>();
|
||||
let mem = self.new_stack(sty);
|
||||
let mem = self.new_stack(pos, sty);
|
||||
for field in fields {
|
||||
let Some(index) = self.tys.find_struct_field(s, field.name) else {
|
||||
self.report(
|
||||
|
@ -4199,6 +4211,23 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
self.ci.unlock();
|
||||
|
||||
for &node in self.ci.nodes[NEVER].inputs.iter() {
|
||||
if self.ci.nodes[node].kind == Kind::Return
|
||||
&& self.ci.nodes[self.ci.nodes.aclass_index(self.ci.nodes[node].inputs[1]).1].kind
|
||||
== Kind::Stck
|
||||
{
|
||||
self.report(
|
||||
self.ci.nodes[node].pos,
|
||||
"returning value with local provenance \
|
||||
(pointer will be invalid after function returns)",
|
||||
);
|
||||
self.report(
|
||||
self.ci.nodes[self.ci.nodes.aclass_index(self.ci.nodes[node].inputs[1]).1].pos,
|
||||
"...the pointer points to stack allocation created here",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if self.errors.borrow().len() == prev_err_len {
|
||||
self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID));
|
||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||
|
@ -4265,7 +4294,7 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn wrap_in_opt(&mut self, val: &mut Value) {
|
||||
fn wrap_in_opt(&mut self, pos: Pos, val: &mut Value) {
|
||||
debug_assert!(!val.var);
|
||||
|
||||
let was_ptr = val.ptr;
|
||||
|
@ -4294,7 +4323,7 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
Loc::Stack => {
|
||||
self.strip_ptr(val);
|
||||
let stack = self.new_stack(oty);
|
||||
let stack = self.new_stack(pos, oty);
|
||||
let fill = self.ci.nodes.new_const(flag_ty, 1);
|
||||
self.store_mem(stack, flag_ty, fill);
|
||||
let off = self.offset(stack, payload_offset);
|
||||
|
@ -4394,7 +4423,7 @@ impl<'a> Codegen<'a> {
|
|||
if inner != src.ty {
|
||||
self.assert_ty(pos, src, inner, hint);
|
||||
}
|
||||
self.wrap_in_opt(src);
|
||||
self.wrap_in_opt(pos, src);
|
||||
} else {
|
||||
debug_assert!(
|
||||
src.ty.is_integer() || src.ty == ty::Id::NEVER,
|
||||
|
@ -4609,6 +4638,7 @@ mod tests {
|
|||
fb_driver;
|
||||
|
||||
// Purely Testing Examples;
|
||||
stack_provenance;
|
||||
advanced_floating_point_arithmetic;
|
||||
nullable_structure;
|
||||
needless_unwrap;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
get_ptr:
|
||||
ADDI64 r254, r254, -8d
|
||||
ADDI64 r1, r254, 0d
|
||||
ADDI64 r254, r254, 8d
|
||||
LI64 r1, 0d
|
||||
JALA r0, r31, 0a
|
||||
main:
|
||||
ADDI64 r254, r254, -40d
|
||||
|
@ -21,6 +19,6 @@ main:
|
|||
1: LD r31, r254, 0a, 40h
|
||||
ADDI64 r254, r254, 40d
|
||||
JALA r0, r31, 0a
|
||||
code size: 208
|
||||
ret: 10
|
||||
code size: 185
|
||||
ret: 0
|
||||
status: Ok(())
|
||||
|
|
|
@ -2,8 +2,8 @@ decide:
|
|||
LI8 r1, 1b
|
||||
JALA r0, r31, 0a
|
||||
main:
|
||||
ADDI64 r254, r254, -224d
|
||||
ST r31, r254, 80a, 144h
|
||||
ADDI64 r254, r254, -232d
|
||||
ST r31, r254, 80a, 152h
|
||||
JAL r31, r0, :decide
|
||||
LI64 r32, 0d
|
||||
ADDI64 r2, r254, 72d
|
||||
|
@ -13,52 +13,54 @@ main:
|
|||
CP r34, r32
|
||||
JMP :1
|
||||
0: CP r34, r33
|
||||
1: JNE r34, r32, :2
|
||||
1: LI64 r35, 1d
|
||||
ST r35, r254, 72a, 8h
|
||||
JNE r34, r32, :2
|
||||
LI64 r1, 9001d
|
||||
JMP :3
|
||||
2: JAL r31, r0, :decide
|
||||
LI8 r35, 0b
|
||||
LI8 r36, 0b
|
||||
ANDI r1, r1, 255d
|
||||
JNE r1, r0, :4
|
||||
LI8 r36, 1b
|
||||
ST r36, r254, 56a, 1h
|
||||
LD r36, r34, 0a, 8h
|
||||
ST r36, r254, 64a, 8h
|
||||
LI8 r37, 1b
|
||||
ST r37, r254, 56a, 1h
|
||||
LD r37, r34, 0a, 8h
|
||||
ST r37, r254, 64a, 8h
|
||||
JMP :5
|
||||
4: ST r35, r254, 56a, 1h
|
||||
5: LD r37, r254, 56a, 1h
|
||||
ANDI r37, r37, 255d
|
||||
ANDI r35, r35, 255d
|
||||
JEQ r37, r35, :6
|
||||
4: ST r36, r254, 56a, 1h
|
||||
5: LD r38, r254, 56a, 1h
|
||||
ANDI r38, r38, 255d
|
||||
ANDI r36, r36, 255d
|
||||
JEQ r38, r36, :6
|
||||
LI64 r1, 42d
|
||||
JMP :3
|
||||
6: JAL r31, r0, :decide
|
||||
LI32 r38, 0w
|
||||
LI32 r39, 0w
|
||||
ANDI r1, r1, 255d
|
||||
JNE r1, r0, :7
|
||||
CP r39, r38
|
||||
CP r40, r39
|
||||
JMP :8
|
||||
7: LI32 r39, 2147483649w
|
||||
8: ANDI r39, r39, 4294967295d
|
||||
ANDI r38, r38, 4294967295d
|
||||
JNE r39, r38, :9
|
||||
7: LI32 r40, 2147483649w
|
||||
8: ANDI r40, r40, 4294967295d
|
||||
ANDI r39, r39, 4294967295d
|
||||
JNE r40, r39, :9
|
||||
LI64 r1, 69d
|
||||
JMP :3
|
||||
9: ADDI64 r3, r254, 40d
|
||||
CP r40, r3
|
||||
CP r41, r3
|
||||
JAL r31, r0, :new_foo
|
||||
ST r1, r254, 40a, 16h
|
||||
LI64 r32, 0d
|
||||
LD r41, r254, 40a, 8h
|
||||
JNE r41, r32, :10
|
||||
LI64 r42, 0d
|
||||
LD r43, r254, 40a, 8h
|
||||
JNE r43, r42, :10
|
||||
LI64 r1, 999d
|
||||
JMP :3
|
||||
10: LRA r4, r0, :"foo\0"
|
||||
CP r3, r40
|
||||
CP r3, r41
|
||||
CP r2, r3
|
||||
LD r2, r2, 0a, 16h
|
||||
JAL r31, r0, :use_foo
|
||||
ADDI64 r42, r254, 0d
|
||||
ADDI64 r44, r254, 0d
|
||||
JAL r31, r0, :no_foo
|
||||
ST r1, r254, 0a, 16h
|
||||
JAL r31, r0, :decide
|
||||
|
@ -68,11 +70,9 @@ main:
|
|||
JMP :12
|
||||
11: CP r2, r33
|
||||
ST r2, r254, 0a, 8h
|
||||
LI64 r43, 1d
|
||||
ST r43, r254, 8a, 8h
|
||||
ST r43, r254, 72a, 8h
|
||||
12: LD r44, r254, 0a, 8h
|
||||
JNE r44, r32, :13
|
||||
ST r35, r254, 8a, 8h
|
||||
12: LD r45, r254, 0a, 8h
|
||||
JNE r45, r42, :13
|
||||
LI64 r1, 34d
|
||||
JMP :3
|
||||
13: ADDI64 r1, r254, 16d
|
||||
|
@ -81,19 +81,19 @@ main:
|
|||
ANDI r1, r1, 255d
|
||||
JNE r1, r0, :14
|
||||
JMP :15
|
||||
14: ST r35, r254, 16a, 1h
|
||||
15: LD r45, r254, 16a, 1h
|
||||
ANDI r45, r45, 255d
|
||||
ANDI r35, r35, 255d
|
||||
JEQ r45, r35, :16
|
||||
14: ST r36, r254, 16a, 1h
|
||||
15: LD r46, r254, 16a, 1h
|
||||
ANDI r46, r46, 255d
|
||||
ANDI r36, r36, 255d
|
||||
JEQ r46, r36, :16
|
||||
LI64 r1, 420d
|
||||
JMP :3
|
||||
16: LD r46, r254, 0a, 8h
|
||||
LD r47, r46, 0a, 8h
|
||||
ANDI r48, r39, 65535d
|
||||
SUB64 r1, r48, r47
|
||||
3: LD r31, r254, 80a, 144h
|
||||
ADDI64 r254, r254, 224d
|
||||
16: LD r47, r254, 0a, 8h
|
||||
LD r48, r47, 0a, 8h
|
||||
ANDI r49, r40, 65535d
|
||||
SUB64 r1, r49, r48
|
||||
3: LD r31, r254, 80a, 152h
|
||||
ADDI64 r254, r254, 232d
|
||||
JALA r0, r31, 0a
|
||||
new_bar:
|
||||
ADDI64 r254, r254, -24d
|
||||
|
|
6
lang/tests/son_tests_stack_provenance.txt
Normal file
6
lang/tests/son_tests_stack_provenance.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
test.hb:5:23: returning value with local provenance (pointer will be invalid after function returns)
|
||||
dangle := fn(): ^uint return &0
|
||||
^
|
||||
test.hb:5:30: ...the pointer points to stack allocation created here
|
||||
dangle := fn(): ^uint return &0
|
||||
^
|
Loading…
Reference in a new issue