authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-21 13:16:47+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-21 16:24:18+02:00
log1d3382202029cde2e00d7747ec0ea53a5df68047
tree168f541921f59956be4d06982467cd636274fefb
parenta0e195120dd3dd7919fd249a6ce2201da9395898

stage2: forbid double dereference in Sema.elemVal


1 files changed, 26 insertions(+), 81 deletions(-)

src/Sema.zig+26-81
...@@ -11494,117 +11494,62 @@ fn elemVal(...@@ -11494,117 +11494,62 @@ fn elemVal(
11494 sema: *Sema,11494 sema: *Sema,
11495 block: *Block,11495 block: *Block,
11496 src: LazySrcLoc,11496 src: LazySrcLoc,
11497 array_maybe_ptr: Air.Inst.Ref,11497 array: Air.Inst.Ref,
11498 elem_index: Air.Inst.Ref,11498 elem_index: Air.Inst.Ref,
11499 elem_index_src: LazySrcLoc,11499 elem_index_src: LazySrcLoc,
11500) CompileError!Air.Inst.Ref {11500) CompileError!Air.Inst.Ref {
11501 const array_ptr_src = src; // TODO better source location11501 const array_src = src; // TODO better source location
11502 const maybe_ptr_ty = sema.typeOf(array_maybe_ptr);11502 const array_ty = sema.typeOf(array);
11503 switch (maybe_ptr_ty.zigTypeTag()) {11503
11504 .Pointer => switch (maybe_ptr_ty.ptrSize()) {11504 if (!array_ty.isIndexable()) {
11505 return sema.fail(block, src, "array access of non-indexable type '{}'", .{array_ty});
11506 }
11507
11508 switch (array_ty.zigTypeTag()) {
11509 .Pointer => switch (array_ty.ptrSize()) {
11505 .Slice => {11510 .Slice => {
11506 const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array_maybe_ptr);11511 const maybe_slice_val = try sema.resolveDefinedValue(block, array_src, array);
11507 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);11512 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
11508 const runtime_src = if (maybe_slice_val) |slice_val| rs: {11513 const runtime_src = if (maybe_slice_val) |slice_val| rs: {
11509 const index_val = maybe_index_val orelse break :rs elem_index_src;11514 const index_val = maybe_index_val orelse break :rs elem_index_src;
11510 const index = @intCast(usize, index_val.toUnsignedInt());11515 const index = @intCast(usize, index_val.toUnsignedInt());
11511 const elem_val = try slice_val.elemValue(sema.arena, index);11516 const elem_val = try slice_val.elemValue(sema.arena, index);
11512 return sema.addConstant(maybe_ptr_ty.elemType2(), elem_val);11517 return sema.addConstant(array_ty.elemType2(), elem_val);
11513 } else array_ptr_src;11518 } else array_src;
1151411519
11515 try sema.requireRuntimeBlock(block, runtime_src);11520 try sema.requireRuntimeBlock(block, runtime_src);
11516 return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index);11521 return block.addBinOp(.slice_elem_val, array, elem_index);
11517 },11522 },
11518 .Many, .C => {11523 .Many, .C => {
11519 if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |ptr_val| {11524 if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| {
11520 _ = ptr_val;11525 _ = ptr_val;
11521 return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{});11526 return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{});
11522 }11527 }
11523 try sema.requireRuntimeBlock(block, src);11528 try sema.requireRuntimeBlock(block, src);
11524 return block.addBinOp(.ptr_elem_val, array_maybe_ptr, elem_index);11529 return block.addBinOp(.ptr_elem_val, array, elem_index);
11525 },11530 },
11526 .One => {11531 .One => {
11527 const indexable_ty = maybe_ptr_ty.childType();11532 assert(array_ty.childType().zigTypeTag() == .Array);
11528 switch (indexable_ty.zigTypeTag()) {11533 const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src);
11529 .Pointer => switch (indexable_ty.ptrSize()) {11534 return sema.analyzeLoad(block, src, elem_ptr, elem_index_src);
11530 .Slice => {
11531 // We have a pointer to a slice and we want an element value.
11532 if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) {
11533 const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
11534 if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| {
11535 _ = slice_val;
11536 return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{});
11537 }
11538 try sema.requireRuntimeBlock(block, src);
11539 return block.addBinOp(.slice_elem_val, slice, elem_index);
11540 }
11541 try sema.requireRuntimeBlock(block, src);
11542 return block.addBinOp(.ptr_slice_elem_val, array_maybe_ptr, elem_index);
11543 },
11544 .Many, .C => {
11545 // We have a pointer to a pointer and we want an element value.
11546 if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) {
11547 const ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
11548 if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| {
11549 _ = ptr_val;
11550 return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{});
11551 }
11552 try sema.requireRuntimeBlock(block, src);
11553 return block.addBinOp(.ptr_elem_val, ptr, elem_index);
11554 }
11555 try sema.requireRuntimeBlock(block, src);
11556 return block.addBinOp(.ptr_ptr_elem_val, array_maybe_ptr, elem_index);
11557 },
11558 .One => {
11559 const array_ty = indexable_ty.childType();
11560 if (array_ty.zigTypeTag() == .Array) {
11561 // We have a double pointer to an array, and we want an element
11562 // value. This can happen with this code for example:
11563 // var a: *[1]u8 = undefined; _ = a[0];
11564 const array_ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src);
11565 const ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
11566 return sema.analyzeLoad(block, src, ptr, elem_index_src);
11567 } else return sema.fail(
11568 block,
11569 array_ptr_src,
11570 "expected pointer, found '{}'",
11571 .{array_ty},
11572 );
11573 },
11574 },
11575 .Array => {
11576 const ptr = try sema.elemPtr(block, src, array_maybe_ptr, elem_index, elem_index_src);
11577 return sema.analyzeLoad(block, src, ptr, elem_index_src);
11578 },
11579 else => return sema.fail(
11580 block,
11581 array_ptr_src,
11582 "expected pointer, found '{}'",
11583 .{indexable_ty},
11584 ),
11585 }
11586 },11535 },
11587 },11536 },
11588 .Array => {11537 .Array => {
11589 if (try sema.resolveMaybeUndefVal(block, src, array_maybe_ptr)) |array_val| {11538 if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| {
11590 const elem_ty = maybe_ptr_ty.childType();11539 const elem_ty = array_ty.childType();
11591 const opt_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
11592 if (array_val.isUndef()) return sema.addConstUndef(elem_ty);11540 if (array_val.isUndef()) return sema.addConstUndef(elem_ty);
11593 if (opt_index_val) |index_val| {11541 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
11542 if (maybe_index_val) |index_val| {
11594 const index = @intCast(usize, index_val.toUnsignedInt());11543 const index = @intCast(usize, index_val.toUnsignedInt());
11595 const elem_val = try array_val.elemValue(sema.arena, index);11544 const elem_val = try array_val.elemValue(sema.arena, index);
11596 return sema.addConstant(elem_ty, elem_val);11545 return sema.addConstant(elem_ty, elem_val);
11597 }11546 }
11598 }11547 }
11599 try sema.requireRuntimeBlock(block, src);11548 try sema.requireRuntimeBlock(block, src);
11600 return block.addBinOp(.array_elem_val, array_maybe_ptr, elem_index);11549 return block.addBinOp(.array_elem_val, array, elem_index);
11601 },11550 },
11602 else => return sema.fail(11551 .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}),
11603 block,11552 else => unreachable,
11604 array_ptr_src,
11605 "expected pointer or array; found '{}'",
11606 .{maybe_ptr_ty},
11607 ),
11608 }11553 }
11609}11554}
1161011555