Rust · 3090 bytes Raw Blame History
1 //! Tolerated-diff proof points for the parity harness.
2
3 mod common;
4
5 use common::harness::diff_macho;
6
7 const MH_MAGIC_64: u32 = 0xFEEDFACF;
8 const CPU_TYPE_ARM64: u32 = 0x0100_000C;
9 const MH_EXECUTE: u32 = 2;
10 const LC_ID_DYLIB: u32 = 0x0D;
11 const LC_UUID: u32 = 0x1B;
12 const LC_CODE_SIGNATURE: u32 = 0x1D;
13
14 #[test]
15 fn differing_uuid_bytes_are_tolerated() {
16 let ours = synth_uuid_image([0x11; 16]);
17 let theirs = synth_uuid_image([0x22; 16]);
18 let report = diff_macho(&ours, &theirs);
19 assert!(
20 report.is_clean(),
21 "UUID-only diff should be tolerated: {report:#?}"
22 );
23 assert_eq!(report.tolerated.len(), 1);
24 }
25
26 #[test]
27 fn differing_code_signature_blob_bytes_are_tolerated() {
28 let ours = synth_code_signature_image([0xAA; 8]);
29 let theirs = synth_code_signature_image([0xBB; 8]);
30 let report = diff_macho(&ours, &theirs);
31 assert!(
32 report.is_clean(),
33 "code-signature-only diff should be tolerated: {report:#?}"
34 );
35 assert_eq!(report.tolerated.len(), 1);
36 }
37
38 #[test]
39 fn differing_dylib_timestamps_are_tolerated() {
40 let ours = synth_dylib_image(2);
41 let theirs = synth_dylib_image(7);
42 let report = diff_macho(&ours, &theirs);
43 assert!(
44 report.is_clean(),
45 "dylib timestamp-only diff should be tolerated: {report:#?}"
46 );
47 assert_eq!(report.tolerated.len(), 1);
48 }
49
50 fn synth_uuid_image(uuid: [u8; 16]) -> Vec<u8> {
51 let mut out = Vec::new();
52 push_header(&mut out, 1, 24);
53 out.extend_from_slice(&LC_UUID.to_le_bytes());
54 out.extend_from_slice(&24u32.to_le_bytes());
55 out.extend_from_slice(&uuid);
56 out
57 }
58
59 fn synth_code_signature_image(blob: [u8; 8]) -> Vec<u8> {
60 let mut out = Vec::new();
61 let dataoff = 0x40u32;
62 let datasize = blob.len() as u32;
63 push_header(&mut out, 1, 16);
64 out.extend_from_slice(&LC_CODE_SIGNATURE.to_le_bytes());
65 out.extend_from_slice(&16u32.to_le_bytes());
66 out.extend_from_slice(&dataoff.to_le_bytes());
67 out.extend_from_slice(&datasize.to_le_bytes());
68 out.resize(dataoff as usize, 0);
69 out.extend_from_slice(&blob);
70 out
71 }
72
73 fn synth_dylib_image(timestamp: u32) -> Vec<u8> {
74 let mut out = Vec::new();
75 let cmdsize = 32u32;
76 push_header(&mut out, 1, cmdsize);
77 out.extend_from_slice(&LC_ID_DYLIB.to_le_bytes());
78 out.extend_from_slice(&cmdsize.to_le_bytes());
79 out.extend_from_slice(&24u32.to_le_bytes());
80 out.extend_from_slice(&timestamp.to_le_bytes());
81 out.extend_from_slice(&0u32.to_le_bytes());
82 out.extend_from_slice(&0u32.to_le_bytes());
83 out.extend_from_slice(b"x\0\0\0\0\0\0\0");
84 out
85 }
86
87 fn push_header(out: &mut Vec<u8>, ncmds: u32, sizeofcmds: u32) {
88 out.extend_from_slice(&MH_MAGIC_64.to_le_bytes());
89 out.extend_from_slice(&CPU_TYPE_ARM64.to_le_bytes());
90 out.extend_from_slice(&0u32.to_le_bytes());
91 out.extend_from_slice(&MH_EXECUTE.to_le_bytes());
92 out.extend_from_slice(&ncmds.to_le_bytes());
93 out.extend_from_slice(&sizeofcmds.to_le_bytes());
94 out.extend_from_slice(&0u32.to_le_bytes());
95 out.extend_from_slice(&0u32.to_le_bytes());
96 }
97