内存安全最难的问题Memory Safety's Hardest Problem
文章将一个来自 Lobsters 社区的评论提取出来作为独立参考,探讨了内存安全领域中最具挑战性的问题。该内容聚焦于系统编程中内存安全机制难以覆盖的边缘情况或设计盲区。
Uplifting a lobsters comment for easier reference.
The central memory safety counter example, the hardest case to solve, doesn’t have anything to do with destructors or heap:
const std = @import("std");
const E = union(enum) {
a: u128,
b: []const u8,
};
pub fn main() void {
const bad_addr: u128 = @intFromPtr(&main);
var e: E = .{ .b = "hello" };
const oh_no_pointer: *const []const u8 = switch (e) {
.a => unreachable,
.b => |*p| p,
};
e = .{ .a = (16 << 64) + bad_addr };
const oh_no: []const u8 = oh_no_pointer.*;
std.debug.print("{s}\n", .{oh_no});
}$ zig run main.zig
��C�� �This sort of example also breaks Ada:
https://www.enyo.de/fw/notes/ada-type-safety.html
We have a tagged union, which can hold either A or B. We initialize the union as A, take a pointer to its internals, overwrite the original with B, and then use the pointer. The pointer is still typed as A, but the bytes it points to now belong to B: a type confusion.
This being said, we care about memory unsafety primarily because it leads to exploitable software, and it’s unclear just how impactful the example above is in practice. It is a happy coincidence that by far the most exploitable memory error in practice, the infamous buffer overflow, is also trivial to fix with compiler-inserted bounds checks. The biggest miss of the industry when it comes to memory safety is not listening to Walter Bright:
https://digitalmars.com/articles/C-biggest-mistake.html
I bet that, had we got char a[..] syntax around C11, quite a few issues wouldn’t have happened!
See also What is Memory Safety?
需要完整排版与评论请前往来源站点阅读。