mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
compiler: avoid use of undefined memory
InternPool is nice in some ways but it also comes with its own set of footguns. This commit fixes 5 instances. I see quite a few Valgrind warnings remaining when running the behavior tests. Perhaps the solution is to have stringToSlice return a struct with start and length as indexes, which has a format function?
This commit is contained in:
parent
69b7b91092
commit
f1c900c72e
@ -576,7 +576,6 @@ pub const Decl = struct {
|
||||
}
|
||||
mod.destroyFunc(func);
|
||||
}
|
||||
_ = mod.memoized_decls.remove(decl.val.ip_index);
|
||||
}
|
||||
|
||||
/// This name is relative to the containing namespace of the decl.
|
||||
@ -690,10 +689,30 @@ pub const Decl = struct {
|
||||
}
|
||||
|
||||
pub fn getFullyQualifiedName(decl: Decl, mod: *Module) !InternPool.NullTerminatedString {
|
||||
const gpa = mod.gpa;
|
||||
if (decl.name_fully_qualified) return decl.name;
|
||||
|
||||
const ip = &mod.intern_pool;
|
||||
const count = count: {
|
||||
var count: usize = ip.stringToSlice(decl.name).len + 1;
|
||||
var ns: Namespace.Index = decl.src_namespace;
|
||||
while (true) {
|
||||
const namespace = mod.namespacePtr(ns);
|
||||
const ns_decl_index = namespace.getDeclIndex(mod);
|
||||
const ns_decl = mod.declPtr(ns_decl_index);
|
||||
count += ip.stringToSlice(ns_decl.name).len + 1;
|
||||
ns = namespace.parent.unwrap() orelse {
|
||||
count += namespace.file_scope.sub_file_path.len;
|
||||
break :count count;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const gpa = mod.gpa;
|
||||
const start = ip.string_bytes.items.len;
|
||||
try decl.renderFullyQualifiedName(mod, ip.string_bytes.writer(gpa));
|
||||
// Protects reads of interned strings from being reallocated during the call to
|
||||
// renderFullyQualifiedName.
|
||||
try ip.string_bytes.ensureUnusedCapacity(gpa, count);
|
||||
decl.renderFullyQualifiedName(mod, ip.string_bytes.writer(gpa)) catch unreachable;
|
||||
|
||||
// Sanitize the name for nvptx which is more restrictive.
|
||||
// TODO This should be handled by the backend, not the frontend. Have a
|
||||
@ -4018,7 +4037,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
|
||||
.unreferenced => false,
|
||||
};
|
||||
|
||||
var decl_prog_node = mod.sema_prog_node.start(mod.intern_pool.stringToSlice(decl.name), 0);
|
||||
var decl_prog_node = mod.sema_prog_node.start("", 0);
|
||||
decl_prog_node.activate();
|
||||
defer decl_prog_node.end();
|
||||
|
||||
@ -5774,9 +5793,11 @@ pub fn createAnonymousDeclFromDecl(
|
||||
const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);
|
||||
errdefer mod.destroyDecl(new_decl_index);
|
||||
const ip = &mod.intern_pool;
|
||||
const name = try ip.getOrPutStringFmt(mod.gpa, "{s}__anon_{d}", .{
|
||||
// This protects the getOrPutStringFmt from reallocating src decl name while reading it.
|
||||
try ip.string_bytes.ensureUnusedCapacity(mod.gpa, ip.stringToSlice(src_decl.name).len + 20);
|
||||
const name = ip.getOrPutStringFmt(mod.gpa, "{s}__anon_{d}", .{
|
||||
ip.stringToSlice(src_decl.name), @enumToInt(new_decl_index),
|
||||
});
|
||||
}) catch unreachable;
|
||||
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);
|
||||
return new_decl_index;
|
||||
}
|
||||
|
||||
@ -17065,6 +17065,7 @@ fn typeInfoNamespaceDecls(
|
||||
seen_namespaces: *std.AutoHashMap(*Namespace, void),
|
||||
) !void {
|
||||
const mod = sema.mod;
|
||||
const ip = &mod.intern_pool;
|
||||
const gop = try seen_namespaces.getOrPut(namespace);
|
||||
if (gop.found_existing) return;
|
||||
const decls = namespace.decls.keys();
|
||||
@ -17081,7 +17082,9 @@ fn typeInfoNamespaceDecls(
|
||||
const name_val = v: {
|
||||
var anon_decl = try block.startAnonDecl();
|
||||
defer anon_decl.deinit();
|
||||
const name = mod.intern_pool.stringToSlice(decl.name);
|
||||
// Protects the decl name slice from being invalidated at the call to intern().
|
||||
try ip.string_bytes.ensureUnusedCapacity(sema.gpa, ip.stringToSlice(decl.name).len + 1);
|
||||
const name = ip.stringToSlice(decl.name);
|
||||
const new_decl_ty = try mod.arrayType(.{
|
||||
.len = name.len,
|
||||
.child = .u8_type,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user