From 641fac5b529f3df9a56c34931168ddccee445e1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Apr 2026 04:39:32 +0000 Subject: [PATCH 1/2] Add unsafe-context borrow checks for indexed mutation Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/6cf3a5da-8b46-4b4e-9611-b71ea014dc25 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../main/test/unsafe/BorrowCheckerUnsafe.cod | 19 ++++++ .../handler/AssignmentHandler.java | 67 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/main/cod/demo/src/main/test/unsafe/BorrowCheckerUnsafe.cod diff --git a/src/main/cod/demo/src/main/test/unsafe/BorrowCheckerUnsafe.cod b/src/main/cod/demo/src/main/test/unsafe/BorrowCheckerUnsafe.cod new file mode 100644 index 0000000..07b2b21 --- /dev/null +++ b/src/main/cod/demo/src/main/test/unsafe/BorrowCheckerUnsafe.cod @@ -0,0 +1,19 @@ +unit test.unsafe (main: this) + +share unsafe BorrowBox { + buffer: u8[4] + + share unsafe trigger() { + buffer[0] = 1 + p: *u8 = &buffer[0] + buffer[0] = 2 + out(*p) + } +} + +share BorrowMain { + share main() { + box: BorrowBox = safe(BorrowBox()) + safe(box.trigger()) + } +} diff --git a/src/main/java/cod/interpreter/handler/AssignmentHandler.java b/src/main/java/cod/interpreter/handler/AssignmentHandler.java index 3112e6f..732dd02 100644 --- a/src/main/java/cod/interpreter/handler/AssignmentHandler.java +++ b/src/main/java/cod/interpreter/handler/AssignmentHandler.java @@ -185,12 +185,14 @@ private Object handleIndexAssignment(IndexAccess indexAccess, Object newValue, E if (arrayObj instanceof NaturalArray) { NaturalArray natural = (NaturalArray) arrayObj; long index = expressionHandler.toLongIndex(indexObj); + ensureNoActiveBorrow(arrayObj, index, ctx); natural.set(index, newValue); return newValue; } if (arrayObj instanceof List) { int intIndex = expressionHandler.toIntIndex(indexObj); + ensureNoActiveBorrow(arrayObj, intIndex, ctx); List list = (List) arrayObj; list.set(intIndex, newValue); return newValue; @@ -328,6 +330,71 @@ private long normalizeListIndex(long index, int size) { } return index; } + + private void ensureNoActiveBorrow(Object container, long index, ExecutionContext ctx) { + if (!isBorrowCheckerActive(ctx)) { + return; + } + if (hasBorrowInLocals(container, index, ctx.getLocalsStack())) { + throw new ProgramError( + "Borrow checker violation: cannot mutate index " + index + + " while it is currently borrowed by an active pointer"); + } + if (ctx.objectInstance != null + && ctx.objectInstance.fields != null + && hasBorrowInMap(container, index, ctx.objectInstance.fields)) { + throw new ProgramError( + "Borrow checker violation: cannot mutate index " + index + + " while it is currently borrowed by an active pointer"); + } + if (ctx.getSlotValues() != null && hasBorrowInMap(container, index, ctx.getSlotValues())) { + throw new ProgramError( + "Borrow checker violation: cannot mutate index " + index + + " while it is currently borrowed by an active pointer"); + } + } + + private boolean isBorrowCheckerActive(ExecutionContext ctx) { + return ctx != null && (ctx.isUnsafeExecutionContext() || (ctx.currentClass != null && ctx.currentClass.isUnsafe)); + } + + private boolean hasBorrowInLocals(Object container, long index, List> scopes) { + if (scopes == null) return false; + for (Map scope : scopes) { + if (hasBorrowInMap(container, index, scope)) { + return true; + } + } + return false; + } + + private boolean hasBorrowInMap(Object container, long index, Map values) { + if (values == null || values.isEmpty()) return false; + for (Object value : values.values()) { + if (containsBorrowForLocation(typeSystem.unwrap(value), container, index)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private boolean containsBorrowForLocation(Object value, Object container, long index) { + if (value == null) return false; + if (value instanceof TypeHandler.PointerValue) { + TypeHandler.PointerValue pointer = (TypeHandler.PointerValue) value; + return pointer.container == container && pointer.index == index; + } + if (value instanceof List) { + List list = (List) value; + for (Object element : list) { + if (containsBorrowForLocation(typeSystem.unwrap(element), container, index)) { + return true; + } + } + } + return false; + } private Object handleVariableAssignment(Expr target, Object newValue, ExecutionContext ctx) { try { From cdb846c02b5b8ecf4cd051ff0f640aae14f74541 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 13 Apr 2026 04:42:27 +0000 Subject: [PATCH 2/2] Enforce borrow checks in unsafe indexed mutations Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/6cf3a5da-8b46-4b4e-9611-b71ea014dc25 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../handler/AssignmentHandler.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/cod/interpreter/handler/AssignmentHandler.java b/src/main/java/cod/interpreter/handler/AssignmentHandler.java index 732dd02..169e94a 100644 --- a/src/main/java/cod/interpreter/handler/AssignmentHandler.java +++ b/src/main/java/cod/interpreter/handler/AssignmentHandler.java @@ -13,6 +13,9 @@ import java.util.*; public class AssignmentHandler { + private static final String BORROW_MUTATION_VIOLATION = + "Borrow checker violation: cannot mutate index %d while it is currently borrowed by an active pointer"; + private final TypeHandler typeSystem; private final Interpreter interpreter; private final ExpressionHandler expressionHandler; @@ -336,24 +339,22 @@ private void ensureNoActiveBorrow(Object container, long index, ExecutionContext return; } if (hasBorrowInLocals(container, index, ctx.getLocalsStack())) { - throw new ProgramError( - "Borrow checker violation: cannot mutate index " + index - + " while it is currently borrowed by an active pointer"); + throwBorrowMutationViolation(index); } if (ctx.objectInstance != null && ctx.objectInstance.fields != null && hasBorrowInMap(container, index, ctx.objectInstance.fields)) { - throw new ProgramError( - "Borrow checker violation: cannot mutate index " + index - + " while it is currently borrowed by an active pointer"); + throwBorrowMutationViolation(index); } if (ctx.getSlotValues() != null && hasBorrowInMap(container, index, ctx.getSlotValues())) { - throw new ProgramError( - "Borrow checker violation: cannot mutate index " + index - + " while it is currently borrowed by an active pointer"); + throwBorrowMutationViolation(index); } } + private void throwBorrowMutationViolation(long index) { + throw new ProgramError(String.format(BORROW_MUTATION_VIOLATION, index)); + } + private boolean isBorrowCheckerActive(ExecutionContext ctx) { return ctx != null && (ctx.isUnsafeExecutionContext() || (ctx.currentClass != null && ctx.currentClass.isUnsafe)); }