mirror of
https://github.com/roc-lang/roc.git
synced 2025-12-11 11:32:28 +00:00
Fix segfault by adding type annotations
This commit is contained in:
parent
d6e802c50f
commit
e2a60faa35
3 changed files with 23 additions and 6 deletions
|
|
@ -1166,22 +1166,26 @@ test "fx platform runtime stack overflow" {
|
||||||
defer allocator.free(run_result.stdout);
|
defer allocator.free(run_result.stdout);
|
||||||
defer allocator.free(run_result.stderr);
|
defer allocator.free(run_result.stderr);
|
||||||
|
|
||||||
// After stack overflow handling is implemented, we expect:
|
// Stack overflow can be caught by either:
|
||||||
// 1. The process exits with code 134 (indicating stack overflow was caught)
|
// 1. The Roc interpreter (exit code 1, "overflowed its stack memory" message) - most common
|
||||||
// 2. Stderr contains a helpful message about stack overflow
|
// 2. The SIGABRT signal handler (exit code 134) - if native stack overflow handling is used
|
||||||
switch (run_result.term) {
|
switch (run_result.term) {
|
||||||
.Exited => |code| {
|
.Exited => |code| {
|
||||||
if (code == 134) {
|
if (code == 134) {
|
||||||
// Stack overflow was caught and handled properly
|
// Stack overflow was caught by native signal handler
|
||||||
// Verify the helpful error message was printed
|
// Verify the helpful error message was printed
|
||||||
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "overflowed its stack memory") != null);
|
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "overflowed its stack memory") != null);
|
||||||
|
} else if (code == 1) {
|
||||||
|
// Stack overflow was caught by the interpreter - this is the expected case
|
||||||
|
// The interpreter detects excessive work stack depth and reports the error
|
||||||
|
try testing.expect(std.mem.indexOf(u8, run_result.stderr, "overflowed its stack memory") != null);
|
||||||
} else if (code == 139) {
|
} else if (code == 139) {
|
||||||
// Exit code 139 = 128 + 11 (SIGSEGV) - stack overflow was NOT handled
|
// Exit code 139 = 128 + 11 (SIGSEGV) - stack overflow was NOT handled
|
||||||
// The Roc program crashed with a segfault that wasn't caught
|
// The Roc program crashed with a segfault that wasn't caught
|
||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
std.debug.print("Stack overflow handling NOT YET IMPLEMENTED for Roc programs.\n", .{});
|
std.debug.print("Stack overflow handling NOT YET IMPLEMENTED for Roc programs.\n", .{});
|
||||||
std.debug.print("Process crashed with SIGSEGV (exit code 139).\n", .{});
|
std.debug.print("Process crashed with SIGSEGV (exit code 139).\n", .{});
|
||||||
std.debug.print("Expected: exit code 134 with stack overflow message\n", .{});
|
std.debug.print("Expected: exit code 1 or 134 with stack overflow message\n", .{});
|
||||||
return error.StackOverflowNotHandled;
|
return error.StackOverflowNotHandled;
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("Unexpected exit code: {}\n", .{code});
|
std.debug.print("Unexpected exit code: {}\n", .{code});
|
||||||
|
|
@ -1194,7 +1198,7 @@ test "fx platform runtime stack overflow" {
|
||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
std.debug.print("Stack overflow handling NOT YET IMPLEMENTED for Roc programs.\n", .{});
|
std.debug.print("Stack overflow handling NOT YET IMPLEMENTED for Roc programs.\n", .{});
|
||||||
std.debug.print("Process was killed by signal: {}\n", .{sig});
|
std.debug.print("Process was killed by signal: {}\n", .{sig});
|
||||||
std.debug.print("Expected: exit code 134 with stack overflow message\n", .{});
|
std.debug.print("Expected: exit code 1 or 134 with stack overflow message\n", .{});
|
||||||
return error.StackOverflowNotHandled;
|
return error.StackOverflowNotHandled;
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
|
|
|
||||||
|
|
@ -9550,6 +9550,11 @@ pub const Interpreter = struct {
|
||||||
pub const WorkStack = struct {
|
pub const WorkStack = struct {
|
||||||
items: std.array_list.AlignedManaged(WorkItem, null),
|
items: std.array_list.AlignedManaged(WorkItem, null),
|
||||||
|
|
||||||
|
/// Maximum work stack size to prevent infinite recursion from hanging.
|
||||||
|
/// When exceeded, triggers a stack overflow error.
|
||||||
|
/// 10,000 items allows deep but not infinite recursion (~1MB memory).
|
||||||
|
pub const max_size: usize = 10_000;
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !WorkStack {
|
pub fn init(allocator: std.mem.Allocator) !WorkStack {
|
||||||
return .{ .items = try std.array_list.AlignedManaged(WorkItem, null).initCapacity(allocator, 64) };
|
return .{ .items = try std.array_list.AlignedManaged(WorkItem, null).initCapacity(allocator, 64) };
|
||||||
}
|
}
|
||||||
|
|
@ -9650,6 +9655,12 @@ pub const Interpreter = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for stack overflow (infinite recursion)
|
||||||
|
if (work_stack.items.items.len > WorkStack.max_size) {
|
||||||
|
self.triggerCrash("This Roc program overflowed its stack memory. This usually means there is infinite recursion somewhere in the code.", false, roc_ops);
|
||||||
|
return error.Crash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should never reach here - return_result should have exited the loop
|
// Should never reach here - return_result should have exited the loop
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,10 @@ parse_range = |range_str| {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
repeat : List(a), U64 -> List(a)
|
||||||
repeat = |list, n| repeat_helper([], list, n)
|
repeat = |list, n| repeat_helper([], list, n)
|
||||||
|
|
||||||
|
repeat_helper : List(a), List(a), U64 -> List(a)
|
||||||
repeat_helper = |acc, list, n| match n {
|
repeat_helper = |acc, list, n| match n {
|
||||||
0 => acc
|
0 => acc
|
||||||
_ => repeat_helper(acc.concat(list), list, n - 1)
|
_ => repeat_helper(acc.concat(list), list, n - 1)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue