Skip to content

Regression: Use-after-free during Cache.unhit #19408

@squeek502

Description

@squeek502

Zig Version

master

Steps to Reproduce and Observed Behavior

Regression caused by #19388

The problematic code is here:

zig/lib/std/Build/Cache.zig

Lines 635 to 639 in 640acf8

// Remove files not in the initial hash.
for (self.files.keys()[input_file_count..]) |*file| {
file.deinit(self.cache.gpa);
}
self.files.shrinkRetainingCapacity(input_file_count);

The files are deinited and then the hash map is shrunk, which causes the already-freed-items to be hashed. Before, this used an ArrayList intead of an ArrayHashMap so the shrink didn't attempt to access the already-freed-items.

Reproduction:

zig init
zig build

make any change to build.zig

zig build

results in (on Windows):

thread 19376 panic: Segmentation fault at address 0xffffffffffffffff
C:\Users\Ryan\Programming\Zig\zig\lib\std\Build\Cache.zig:65:46: 0xeeb63c in hash (zig.exe.obj)
        return @truncate(std.hash.Wyhash.hash(pp.prefix, pp.sub_path));
                                             ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\Build\Cache.zig:323:43: 0xa0117b in hash (zig.exe.obj)
            return file.prefixed_path.hash();
                                          ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1849:28: 0x6f66ee in checkedHash__anon_79003 (zig.exe.obj)
            return ctx.hash(key);
                           ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1634:87: 0x1391d4b in getSlotByIndex__anon_115743 (zig.exe.obj)
            const h = if (store_hash) slice.items(.hash)[entry_index] else checkedHash(ctx, slice.items(.key)[entry_index]);
                                                                                      ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1599:45: 0xeebc8f in removeFromIndexByIndexGeneric__anon_105092 (zig.exe.obj)
            const slot = self.getSlotByIndex(entry_index, ctx, header, I, indexes);
                                            ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1593:58: 0xa017c1 in removeFromIndexByIndex (zig.exe.obj)
                .u8 => self.removeFromIndexByIndexGeneric(entry_index, ctx, header, u8, header.indexes(u8)),
                                                         ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1379:48: 0x6f8707 in shrinkRetainingCapacityContext (zig.exe.obj)
                    self.removeFromIndexByIndex(i, if (store_hash) {} else ctx, header);
                                               ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\array_hash_map.zig:1367:55: 0x428a2f in shrinkRetainingCapacity (zig.exe.obj)
            return self.shrinkRetainingCapacityContext(new_len, undefined);
                                                      ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\Build\Cache.zig:639:43: 0x2511c2 in unhit (zig.exe.obj)
        self.files.shrinkRetainingCapacity(input_file_count);
                                          ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\Build\Cache.zig:605:27: 0x24f935 in hit (zig.exe.obj)
                self.unhit(bin_digest, input_file_count);
                          ^
C:\Users\Ryan\Programming\Zig\zig\src\Compilation.zig:2003:35: 0x2b09ec in update (zig.exe.obj)
            const is_hit = man.hit() catch |err| {
                                  ^
C:\Users\Ryan\Programming\Zig\zig\src\main.zig:4507:24: 0x2e3212 in updateModule (zig.exe.obj)
        try comp.update(main_progress_node);
                       ^
C:\Users\Ryan\Programming\Zig\zig\src\main.zig:5250:25: 0x36b428 in cmdBuild (zig.exe.obj)
            updateModule(comp, color) catch |err| switch (err) {
                        ^
C:\Users\Ryan\Programming\Zig\zig\src\main.zig:276:24: 0x18433b in mainArgs (zig.exe.obj)
        return cmdBuild(gpa, arena, cmd_args);
                       ^
C:\Users\Ryan\Programming\Zig\zig\src\main.zig:206:20: 0x18151e in main (zig.exe.obj)
    return mainArgs(gpa, arena, args);
                   ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\start.zig:484:5: 0x18124a in main (zig.exe.obj)
    return callMainWithArgs(@as(usize, @intCast(c_argc)), @as([*][*:0]u8, @ptrCast(c_argv)), envp);
    ^
C:\Users\Ryan\Programming\Zig\zig\lib\libc\mingw\crt\crtexe.c:267:0: 0x294b7c4 in __tmainCRTStartup (crt2.obj)
    mainret = _tmain (argc, argv, envp);

C:\Users\Ryan\Programming\Zig\zig\lib\libc\mingw\crt\crtexe.c:188:0: 0x294b81b in mainCRTStartup (crt2.obj)
  ret = __tmainCRTStartup ();

???:?:?: 0x7ffe569f7343 in ??? (KERNEL32.DLL)
???:?:?: 0x7ffe571426b0 in ??? (ntdll.dll)

Expected Behavior

No use-after-free

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorregressionIt worked in a previous version of Zig, but stopped working.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions