authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-19 20:29:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-22 07:59:23+02:00
logc15e03ac7949205958b1eb66ddbba8dffd944bff
tree2f61419ba307fa30f7bbf769dac24b5d8f817580
parent5b9eaf2938b6fb937e9ed6fb9d19bf4c68f3bdc8

macho: fix bug in incorrectly splicing nodes in trie


2 files changed, 53 insertions(+), 11 deletions(-)

src/link/MachO/Object.zig+1-1
...@@ -6,7 +6,7 @@ const assert = std.debug.assert;...@@ -6,7 +6,7 @@ const assert = std.debug.assert;
6const dwarf = std.dwarf;6const dwarf = std.dwarf;
7const fs = std.fs;7const fs = std.fs;
8const io = std.io;8const io = std.io;
9const log = std.log.scoped(.macho);9const log = std.log.scoped(.link);
10const macho = std.macho;10const macho = std.macho;
11const math = std.math;11const math = std.math;
12const mem = std.mem;12const mem = std.mem;
src/link/MachO/Trie.zig+52-10
...@@ -108,7 +108,7 @@ pub const Node = struct {...@@ -108,7 +108,7 @@ pub const Node = struct {
108 .label = to_label,108 .label = to_label,
109 });109 });
110110
111 return if (match == label.len) to_node else mid.put(allocator, label[match..]);111 return if (match == label.len) mid else mid.put(allocator, label[match..]);
112 }112 }
113113
114 // Add a new node.114 // Add a new node.
...@@ -489,6 +489,21 @@ test "Trie basic" {...@@ -489,6 +489,21 @@ test "Trie basic" {
489 }489 }
490}490}
491491
492fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void {
493 assert(expected.len > 0);
494 if (mem.eql(u8, expected, given)) return;
495 const expected_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(expected)});
496 defer testing.allocator.free(expected_fmt);
497 const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{std.fmt.fmtSliceHexLower(given)});
498 defer testing.allocator.free(given_fmt);
499 const idx = mem.indexOfDiff(u8, expected_fmt, given_fmt).?;
500 var padding = try testing.allocator.alloc(u8, idx + 5);
501 defer testing.allocator.free(padding);
502 mem.set(u8, padding, ' ');
503 std.debug.print("\nEXP: {s}\nGIV: {s}\n{s}^ -- first differing byte\n", .{ expected_fmt, given_fmt, padding });
504 return error.TestFailed;
505}
506
492test "write Trie to a byte stream" {507test "write Trie to a byte stream" {
493 var gpa = testing.allocator;508 var gpa = testing.allocator;
494 var trie: Trie = .{};509 var trie: Trie = .{};
...@@ -523,16 +538,14 @@ test "write Trie to a byte stream" {...@@ -523,16 +538,14 @@ test "write Trie to a byte stream" {
523 defer gpa.free(buffer);538 defer gpa.free(buffer);
524 var stream = std.io.fixedBufferStream(buffer);539 var stream = std.io.fixedBufferStream(buffer);
525 {540 {
526 const nwritten = try trie.write(stream.writer());541 _ = try trie.write(stream.writer());
527 try testing.expect(nwritten == trie.size);542 try expectEqualHexStrings(&exp_buffer, buffer);
528 try testing.expect(mem.eql(u8, buffer, &exp_buffer));
529 }543 }
530 {544 {
531 // Writing finalized trie again should yield the same result.545 // Writing finalized trie again should yield the same result.
532 try stream.seekTo(0);546 try stream.seekTo(0);
533 const nwritten = try trie.write(stream.writer());547 _ = try trie.write(stream.writer());
534 try testing.expect(nwritten == trie.size);548 try expectEqualHexStrings(&exp_buffer, buffer);
535 try testing.expect(mem.eql(u8, buffer, &exp_buffer));
536 }549 }
537}550}
538551
...@@ -562,8 +575,37 @@ test "parse Trie from byte stream" {...@@ -562,8 +575,37 @@ test "parse Trie from byte stream" {
562 var out_buffer = try gpa.alloc(u8, trie.size);575 var out_buffer = try gpa.alloc(u8, trie.size);
563 defer gpa.free(out_buffer);576 defer gpa.free(out_buffer);
564 var out_stream = std.io.fixedBufferStream(out_buffer);577 var out_stream = std.io.fixedBufferStream(out_buffer);
565 const nwritten = try trie.write(out_stream.writer());578 _ = try trie.write(out_stream.writer());
579 try expectEqualHexStrings(&in_buffer, out_buffer);
580}
566581
567 try testing.expect(nwritten == trie.size);582test "ordering bug" {
568 try testing.expect(mem.eql(u8, &in_buffer, out_buffer));583 var gpa = testing.allocator;
584 var trie: Trie = .{};
585 defer trie.deinit(gpa);
586
587 try trie.put(gpa, .{
588 .name = "_asStr",
589 .vmaddr_offset = 0x558,
590 .export_flags = 0,
591 });
592 try trie.put(gpa, .{
593 .name = "_a",
594 .vmaddr_offset = 0x8008,
595 .export_flags = 0,
596 });
597 try trie.finalize(gpa);
598
599 const exp_buffer = [_]u8{
600 0x00, 0x01, 0x5F, 0x61, 0x00, 0x06, 0x04, 0x00,
601 0x88, 0x80, 0x02, 0x01, 0x73, 0x53, 0x74, 0x72,
602 0x00, 0x12, 0x03, 0x00, 0xD8, 0x0A, 0x00,
603 };
604
605 var buffer = try gpa.alloc(u8, trie.size);
606 defer gpa.free(buffer);
607 var stream = std.io.fixedBufferStream(buffer);
608 // Writing finalized trie again should yield the same result.
609 _ = try trie.write(stream.writer());
610 try expectEqualHexStrings(&exp_buffer, buffer);
569}611}