From 5e58657d933a4bbdf7949ad98eeb95e9f62684ee Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:07:32 +0900 Subject: [PATCH 1/7] chore: track issue 88 remediation --- Docs/issue-remediation-progress.md | 57 ++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 Docs/issue-remediation-progress.md diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md new file mode 100644 index 0000000..fdefcfb --- /dev/null +++ b/Docs/issue-remediation-progress.md @@ -0,0 +1,57 @@ +# Issue remediation progress + +Base: `main` at `3d31a8b70d656c1ebcf5299d71b33f7409047f54` + +Delivery order: + +1. #88 bounded file-backed Objective-C root sections +2. #87 bounded loaded Objective-C RW extension arrays + +## Current issue: #88 + +Branch: `codex/issue-88-bounded-file-objc-roots` + +Goal: + +- Make file-backed class, nonlazy-class, protocol, category, nonlazy-category, + and category2 root sections reject malformed raw coordinates, pointer tables, + and referenced layouts without overflow, trapping I/O, or narrowing. +- Preserve readable root order and other root kinds while emitting typed + degradation through the diagnostic owner introduced by #83. + +Confirmed scope: + +- Raw 32/64-bit file section and containing-segment coordinates. +- Regular Mach-O, dyld concatenated-file, and cache subfile/local offset + semantics. +- Whole pointer-table and per-entry referenced-layout validation. +- Additive Diagnostics SPI file-root aggregate and legacy property parity. +- PrivateHeaderKit file-mode root diagnostic ingestion through the existing + bounded member channel. + +Required invariants: + +- Reuse #83's neutral table reader, checked coordinate owner, entry/byte + budgets, and `ObjCMetadataTableDiagnostic`; add no parallel budget or report. +- Absent/wrong-bitness is `nil` without a diagnostic; a legal empty section is + `[]`; a malformed table is empty plus one table diagnostic; a malformed entry + is omitted with an indexed diagnostic while later siblings remain ordered. +- Existing twelve file root properties keep their signatures and project the + checked result; `ObjCSectionRepresentable` gains no requirement. +- Loaded roots, regular member tables, RW-extension arrays, loaded image-info, + and C-string hardening are outside #88. + +Validation gate: + +- Deterministic 32/64 regular-file boundary, truncation, coordinate overflow, + budget/remainder, and good/bad/good fixtures. +- Deterministic cache/subfile coordinate fixture or an equivalent targeted + contract test at the offset owner. +- #60, #65, #79, #83 regressions; Debug/Release and Apple cross-builds. +- Exact MachOObjCSection → MachOSwiftSection → PrivateHeaderKit pin coherence. +- PrivateHeaderKit full tests, release-script tests, codex-review, Ready PR, + GitHub review/CI, then merge to `main`. + +Status: + +- Implementation owner and cache/subfile semantics are under parallel audit. From 2fd7a2b4c31090f227991b8abb35cd70b4d43360 Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:22:47 +0900 Subject: [PATCH 2/7] docs: approve issue 88 design gate --- Docs/issue-remediation-progress.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md index fdefcfb..efda682 100644 --- a/Docs/issue-remediation-progress.md +++ b/Docs/issue-remediation-progress.md @@ -54,4 +54,26 @@ Validation gate: Status: -- Implementation owner and cache/subfile semantics are under parallel audit. +- Design gate approved: + - add Diagnostics SPI `ObjCFileRootReadResult` and + `MachOFile.ObjectiveC.readRoots()` with the twelve existing root values and + ordered table diagnostics; + - use neutral `ObjCMetadataTableDiagnostic.RootSection` as the vocabulary, + preserving `LoadedImageRootSection` and `FileRootSection` as source aliases; + - add `.fileRoot(section:pointerWidth:)` without changing the loaded owner; + - find raw `Section64`/`SegmentCommand64` or 32-bit equivalents together and + validate coordinates without existential getters; + - derive one canonical logical field offset: ordinary section file offset, or + cache section address minus main-cache shared-region start; + - resolve physical backing only through `fileHandleAndOffset(forOffset:)`, + which adds an ordinary fat-slice header offset or maps to the correct cache + subfile-local offset; + - for a nonempty ordinary section, require raw section file offset to equal + the segment-mapped offset; allow a legal zero-size coalesced section to + succeed before that equality or any backing lookup; + - retain the shared count/byte budgets and per-entry checked resolver, and + make all legacy root properties projections of their targeted checked read. +- A read-only survey of 6,288 Objective-C root sections in the current macOS + shared cache found zero nonempty file/VM offset mismatches. General Mach-O and + dyld-cache address conversion owners remain unchanged; #88 is isolated to the + file-root boundary. From 4466a8400abef19504428ddf4db2e25fb72aaa13 Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:23:14 +0900 Subject: [PATCH 3/7] docs: tighten issue 88 cache coordinates --- Docs/issue-remediation-progress.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md index efda682..897835b 100644 --- a/Docs/issue-remediation-progress.md +++ b/Docs/issue-remediation-progress.md @@ -68,9 +68,10 @@ Status: - resolve physical backing only through `fileHandleAndOffset(forOffset:)`, which adds an ordinary fat-slice header offset or maps to the correct cache subfile-local offset; - - for a nonempty ordinary section, require raw section file offset to equal - the segment-mapped offset; allow a legal zero-size coalesced section to - succeed before that equality or any backing lookup; + - for every nonempty file-backed section, including cache images, require raw + section file offset to equal the segment-mapped offset; allow a legal + zero-size coalesced section to succeed before that equality or any backing + lookup; - retain the shared count/byte budgets and per-entry checked resolver, and make all legacy root properties projections of their targeted checked read. - A read-only survey of 6,288 Objective-C root sections in the current macOS From d4dce72e7fba158d36a5bd62e3f51f1f9b125cff Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 12:34:57 +0900 Subject: [PATCH 4/7] docs: record issue 88 root checkpoint --- Docs/issue-remediation-progress.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md index 897835b..ebc1e16 100644 --- a/Docs/issue-remediation-progress.md +++ b/Docs/issue-remediation-progress.md @@ -78,3 +78,17 @@ Status: shared cache found zero nonempty file/VM offset mismatches. General Mach-O and dyld-cache address conversion owners remain unchanged; #88 is isolated to the file-root boundary. +- MachOObjCSection checkpoint + `6a63b4fd7950ab5a61502047070d3ff075011108` adds the file-root aggregate, + twelve compatibility projections, typed section/segment discovery, bounded + root and referenced-layout reads, Diagnostics SPI cases, and 32/64-bit + deterministic fixtures. Checkpoint + `15f727003bf031b300dff1f92fb57a6cdf01d282` moves file/loaded roots onto one + neutral root table/pointer owner and pins zero-size and mapping-failure + precedence. +- A temporary probe against the iOS 27 beta `24A5390f` shared cache found + TrialProto's nonempty `__objc_classlist` in subcache `.01`: canonical logical + offset `0x845e39e8` resolved through `fileHandleAndOffset(forOffset:)` to + physical-local `0x6f279e8`, matching `cacheAndFileOffset`. `readRoots()` + returned 226 classes and zero diagnostics. The probe was removed completely; + deterministic tests retain the logical-domain and backing-boundary contracts. From 808603d58d2d40fd085eb17c13b1d99bb7ba713e Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:22:30 +0900 Subject: [PATCH 5/7] fix: bound file-backed Objective-C roots --- Docs/generation.md | 17 ++-- Docs/issue-remediation-progress.md | 15 +++ Package.resolved | 6 +- Package.swift | 4 +- .../PrivateHeaderKitRawDumpMain.swift | 6 +- .../RawDumpObjCDiagnostics.swift | 16 +++ .../PrivateHeaderKitHelperProtocolTests.swift | 4 +- .../ObjCMemberListDiagnosticsTests.swift | 98 +++++++++++++++++++ 8 files changed, 149 insertions(+), 17 deletions(-) diff --git a/Docs/generation.md b/Docs/generation.md index 6449df9..e6df7ae 100644 --- a/Docs/generation.md +++ b/Docs/generation.md @@ -145,14 +145,15 @@ valid entry. Both preserve outer-table order and validate the outer table and each nonempty inner member table before decoding; an empty inner list does not require an otherwise unused entry size. Regular method, property, and ivar tables use the same finite count and byte budgets, checked arithmetic, and -complete-range validation. Loaded class, protocol, and category root tables -validate both the complete pointer table and each referenced layout before -decoding. One malformed relative list, regular member-table entry, loaded-root -entry, or loaded class/category relationship preserves its readable siblings -and produces a typed degradation; unloaded relative lists are skipped without -warning. These guarantees cover structural table, list, and layout ranges; they -do not validate referenced C strings, loaded class RW-extension arrays, or -file-backed root-section tables. Once that target is published, +complete-range validation. File-backed and loaded class, protocol, and category +root tables validate both the complete pointer table and each referenced layout +before decoding. File-backed roots also validate raw section/segment coordinates +and map cache offsets to their actual subcache backing. One malformed relative +list, regular member-table entry, root entry, or loaded class/category +relationship preserves its readable siblings and produces a typed degradation; +unloaded relative lists are skipped without warning. These guarantees cover +structural table, list, and layout ranges; they do not validate referenced C +strings or loaded class RW-extension arrays. Once that target is published, PrivateHeaderKit reports the precise owner and degradation as an `objc-metadata-warning` and persists the warning in `generation.sqlite`. A bounded diagnostics report records when additional warnings were omitted, so diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md index ebc1e16..d55a03e 100644 --- a/Docs/issue-remediation-progress.md +++ b/Docs/issue-remediation-progress.md @@ -92,3 +92,18 @@ Status: physical-local `0x6f279e8`, matching `cacheAndFileOffset`. `readRoots()` returned 226 classes and zero diagnostics. The probe was removed completely; deterministic tests retain the logical-domain and backing-boundary contracts. +- Final MachOObjCSection cohort commit + `8f0ff76f02c0865422a72662177b5e687e43522d` passed 124 focused regressions, + Debug/Release and Apple cross-builds, the real cache probe, independent audit, + and codex-review with no findings. +- MachOSwiftSection cohort commit + `06ed57ab39fc24956f9079beeb407fffa30d50f4` pins that exact reader. Its six + ObjC-ancestor tests and Release product build passed; codex-review job + `F6B1C8EF-F779-4871-A779-93A953F9FED1` found no issue. +- PrivateHeaderKit now consumes `readRoots()` for file-backed images, retains + file-root diagnostics in the existing bounded report, pins both cohort SHAs, + and covers the wire mapping with a malformed 64-bit class-list fixture. + Swift 6.3.2 ran 625 tests successfully; the macOS Release build, + release-script contracts, Swift 6.3.2 iOS/watchOS Core and test cross-builds, + and both simulator-helper Release cross-builds passed. An independent + consumer audit found no P1/P2 issue. diff --git a/Package.resolved b/Package.resolved index a5f3afe..c9c2268 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "bf9bc82de8b74cbd9b5723f3edfea31631e1790a92b45368c79b146d9e3fe49b", + "originHash" : "2c8b98637386e53b99342869664c9fbadf31a1d488329018a54eb9de7ae90553", "pins" : [ { "identity" : "associatedobject", @@ -59,7 +59,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/lynnswap/MachOObjCSection.git", "state" : { - "revision" : "41a1652d95c34bbb2fdf32ba4b7f5cd9d3ba20ba" + "revision" : "8f0ff76f02c0865422a72662177b5e687e43522d" } }, { @@ -67,7 +67,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/lynnswap/MachOSwiftSection.git", "state" : { - "revision" : "3344bd04e6c0819b17df126bea57bae1bbed3022" + "revision" : "06ed57ab39fc24956f9079beeb407fffa30d50f4" } }, { diff --git a/Package.swift b/Package.swift index 7ff494b..a0d2693 100644 --- a/Package.swift +++ b/Package.swift @@ -37,7 +37,7 @@ let package = Package( ), .package( url: "https://github.com/lynnswap/MachOObjCSection.git", - revision: "41a1652d95c34bbb2fdf32ba4b7f5cd9d3ba20ba" + revision: "8f0ff76f02c0865422a72662177b5e687e43522d" ), .package( url: "https://github.com/MxIris-Reverse-Engineering/swift-objc-dump.git", @@ -45,7 +45,7 @@ let package = Package( ), .package( url: "https://github.com/lynnswap/MachOSwiftSection.git", - revision: "3344bd04e6c0819b17df126bea57bae1bbed3022" + revision: "06ed57ab39fc24956f9079beeb407fffa30d50f4" ), .package( url: "https://github.com/MxIris-Reverse-Engineering/swift-demangling", diff --git a/Sources/PrivateHeaderKitRawDumpCore/PrivateHeaderKitRawDumpMain.swift b/Sources/PrivateHeaderKitRawDumpCore/PrivateHeaderKitRawDumpMain.swift index a78de1d..2343df9 100644 --- a/Sources/PrivateHeaderKitRawDumpCore/PrivateHeaderKitRawDumpMain.swift +++ b/Sources/PrivateHeaderKitRawDumpCore/PrivateHeaderKitRawDumpMain.swift @@ -1159,7 +1159,9 @@ private func dumpObjC( var metadata: CollectedObjCMetadata switch machO { case .file(let file): - metadata = collectObjCMetadata(from: file.objc, in: machO, options: options) + let roots = file.objc.readRoots() + options.objcDiagnostics.append(contentsOf: roots.tableDiagnostics) + metadata = collectObjCMetadata(from: roots, in: machO, options: options) case .loaded(let image): let roots = image.objc.readRoots() options.objcDiagnostics.append(contentsOf: roots.tableDiagnostics) @@ -1216,7 +1218,7 @@ private protocol RawDumpObjCRoots { var categories2_32: [ObjCCategory32]? { get } } -extension MachOFile.ObjectiveC: RawDumpObjCRoots {} +extension ObjCFileRootReadResult: RawDumpObjCRoots {} extension ObjCImageRootReadResult: RawDumpObjCRoots {} @discardableResult diff --git a/Sources/PrivateHeaderKitRawDumpCore/RawDumpObjCDiagnostics.swift b/Sources/PrivateHeaderKitRawDumpCore/RawDumpObjCDiagnostics.swift index 2b917b7..bbfeee3 100644 --- a/Sources/PrivateHeaderKitRawDumpCore/RawDumpObjCDiagnostics.swift +++ b/Sources/PrivateHeaderKitRawDumpCore/RawDumpObjCDiagnostics.swift @@ -279,6 +279,11 @@ private func rawDumpMetadataTableDiagnostic( case let .member(subject, kind): ownerDescription = subjectDescription(subject) metadataDescription = "\(metadataTableMemberKindDescription(kind)) metadata table" + case let .fileRoot(section, pointerWidth): + ownerDescription = "Objective-C file-backed roots" + metadataDescription = + "\(pointerWidthDescription(pointerWidth))" + + " \(rootSectionDescription(section)) root table" case let .loadedImageRoot(section, pointerWidth): ownerDescription = "Objective-C loaded-image roots" metadataDescription = @@ -632,6 +637,17 @@ private func failureDescription( "list pointer could not be rebased" case .missingListBackingData: "list pointer has no readable backing data" + case let .invalidFileRootOffset(sectionAddress, sharedRegionStart): + "root section address \(sectionAddress) cannot be represented relative" + + " to shared-region start \(sharedRegionStart)" + case .missingFileRootBackingData(let sectionAddress): + "root section at address \(sectionAddress) has no readable backing data" + case .unresolvedFileRootPointer(let rawValue): + "root pointer value \(rawValue) could not be rebased" + case .invalidReferencedFileOffset(let offset): + "resolved root offset \(offset) cannot be represented" + case .missingReferencedFileBackingData(let logicalOffset): + "resolved root at logical offset \(logicalOffset) has no readable backing data" case let .unreadableFileHeader(offset, byteCount): "file header at offset \(offset) is not readable for \(byteCount) bytes" case .invalidEntryLogicalOffset: diff --git a/Tests/PrivateHeaderKitHelperProtocolTests/PrivateHeaderKitHelperProtocolTests.swift b/Tests/PrivateHeaderKitHelperProtocolTests/PrivateHeaderKitHelperProtocolTests.swift index 5013fcc..7443cc2 100644 --- a/Tests/PrivateHeaderKitHelperProtocolTests/PrivateHeaderKitHelperProtocolTests.swift +++ b/Tests/PrivateHeaderKitHelperProtocolTests/PrivateHeaderKitHelperProtocolTests.swift @@ -292,7 +292,7 @@ struct PrivateHeaderKitHelperProtocolTests { let state = try #require(pin["state"] as? [String: Any]) #expect(pin["location"] as? String == "https://github.com/lynnswap/MachOObjCSection.git") - #expect(state["revision"] as? String == "41a1652d95c34bbb2fdf32ba4b7f5cd9d3ba20ba") + #expect(state["revision"] as? String == "8f0ff76f02c0865422a72662177b5e687e43522d") #expect(state["version"] == nil) let swiftSectionPin = try #require( @@ -307,7 +307,7 @@ struct PrivateHeaderKitHelperProtocolTests { ) #expect( swiftSectionState["revision"] as? String - == "3344bd04e6c0819b17df126bea57bae1bbed3022" + == "06ed57ab39fc24956f9079beeb407fffa30d50f4" ) #expect(swiftSectionState["version"] == nil) diff --git a/Tests/PrivateHeaderKitRawDumpTests/ObjCMemberListDiagnosticsTests.swift b/Tests/PrivateHeaderKitRawDumpTests/ObjCMemberListDiagnosticsTests.swift index c649bc6..307a794 100644 --- a/Tests/PrivateHeaderKitRawDumpTests/ObjCMemberListDiagnosticsTests.swift +++ b/Tests/PrivateHeaderKitRawDumpTests/ObjCMemberListDiagnosticsTests.swift @@ -6,6 +6,27 @@ import Testing @testable import PrivateHeaderKitRawDumpCore struct ObjCMemberListDiagnosticsTests { + @Test func fileRootDiagnosticsUseTheExistingBoundedMemberChannel() throws { + let fixture = try InvalidFileRootFixture() + let result = fixture.machO.objc.readRoots() + + #expect(result.classes64?.isEmpty == true) + #expect(result.tableDiagnostics.count == 1) + + let accumulator = RawDumpObjCDiagnosticsAccumulator() + accumulator.append(contentsOf: result.tableDiagnostics) + + let report = accumulator.report + #expect(report.diagnostics.count == 1) + #expect(report.omittedDiagnosticCount == 0) + #expect(report.diagnostics.first?.owner == "Objective-C file-backed roots") + #expect( + report.diagnostics.first?.degradation + == "64-bit class-list root table could not be fully read:" + + " section size 9 is not a multiple of pointer size 8" + ) + } + @Test func regularTableDiagnosticsUseTheExistingBoundedMemberChannel() throws { let fixture = try InvalidMemberListFixture( memberDiagnosticCount: 0, @@ -223,6 +244,64 @@ struct ObjCMemberListDiagnosticsTests { } } +private final class InvalidFileRootFixture { + let machO: MachOFile + private let url: URL + + init() throws { + let fileSize = 0x1000 + let rootOffset = 0x400 + let vmAddress: UInt64 = 0x1_0000_0000 + var data = Data(count: fileSize) + + var header = mach_header_64() + header.magic = UInt32(MH_MAGIC_64) + header.cputype = CPU_TYPE_ARM64 + header.cpusubtype = CPU_SUBTYPE_ARM64_ALL + header.filetype = UInt32(MH_DYLIB) + header.ncmds = 1 + header.sizeofcmds = UInt32( + MemoryLayout.size + MemoryLayout.size + ) + data.storeValue(header, at: 0) + + var segment = segment_command_64() + segment.cmd = UInt32(LC_SEGMENT_64) + segment.cmdsize = header.sizeofcmds + segment.vmaddr = vmAddress + segment.vmsize = UInt64(fileSize) + segment.fileoff = 0 + segment.filesize = UInt64(fileSize) + segment.maxprot = VM_PROT_READ + segment.initprot = VM_PROT_READ + segment.nsects = 1 + segment.writeName("__DATA") + data.storeValue(segment, at: MemoryLayout.size) + + var section = section_64() + section.addr = vmAddress + UInt64(rootOffset) + section.size = 9 + section.offset = UInt32(rootOffset) + section.align = 3 + section.writeSectionName("__objc_classlist", segmentName: "__DATA") + data.storeValue( + section, + at: MemoryLayout.size + + MemoryLayout.size + ) + + url = FileManager.default.temporaryDirectory.appendingPathComponent( + "PrivateHeaderKitInvalidFileRoot-\(UUID().uuidString)" + ) + try data.write(to: url) + machO = try MachOFile(url: url) + } + + deinit { + try? FileManager.default.removeItem(at: url) + } +} + private final class InvalidMemberListFixture { let machO: MachOFile let objcClass: ObjCClass64 @@ -449,6 +528,25 @@ private struct RawIvar64 { let size: UInt32 } +private extension segment_command_64 { + mutating func writeName(_ value: String) { + Swift.withUnsafeMutableBytes(of: &segname) { destination in + destination.copyBytes(from: value.utf8) + } + } +} + +private extension section_64 { + mutating func writeSectionName(_ value: String, segmentName: String) { + Swift.withUnsafeMutableBytes(of: §name) { destination in + destination.copyBytes(from: value.utf8) + } + Swift.withUnsafeMutableBytes(of: &segname) { destination in + destination.copyBytes(from: segmentName.utf8) + } + } +} + private extension Data { func loadValue(_ type: Value.Type, at offset: Int) -> Value { self[offset..<(offset + MemoryLayout.size)].withUnsafeBytes { From 8674f4fec6c9822f18bb1cf03a5c065134843dc5 Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:26:10 +0900 Subject: [PATCH 6/7] chore: record issue 88 validation --- Docs/issue-remediation-progress.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md index d55a03e..5c89d6b 100644 --- a/Docs/issue-remediation-progress.md +++ b/Docs/issue-remediation-progress.md @@ -107,3 +107,6 @@ Status: release-script contracts, Swift 6.3.2 iOS/watchOS Core and test cross-builds, and both simulator-helper Release cross-builds passed. An independent consumer audit found no P1/P2 issue. +- Final branch-wide codex-review against `main` found no issue (job + `0628D06C-89D9-4A26-9079-DA2252DDEEAA`). Issue #88 is ready for delivery; + remove this temporary ledger before opening the PR. From 309be879f089b07eac2933f8be60e7e3764d0323 Mon Sep 17 00:00:00 2001 From: Kazuki Nakashima <65545348+lynnswap@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:26:18 +0900 Subject: [PATCH 7/7] chore: remove completed issue ledger --- Docs/issue-remediation-progress.md | 112 ----------------------------- 1 file changed, 112 deletions(-) delete mode 100644 Docs/issue-remediation-progress.md diff --git a/Docs/issue-remediation-progress.md b/Docs/issue-remediation-progress.md deleted file mode 100644 index 5c89d6b..0000000 --- a/Docs/issue-remediation-progress.md +++ /dev/null @@ -1,112 +0,0 @@ -# Issue remediation progress - -Base: `main` at `3d31a8b70d656c1ebcf5299d71b33f7409047f54` - -Delivery order: - -1. #88 bounded file-backed Objective-C root sections -2. #87 bounded loaded Objective-C RW extension arrays - -## Current issue: #88 - -Branch: `codex/issue-88-bounded-file-objc-roots` - -Goal: - -- Make file-backed class, nonlazy-class, protocol, category, nonlazy-category, - and category2 root sections reject malformed raw coordinates, pointer tables, - and referenced layouts without overflow, trapping I/O, or narrowing. -- Preserve readable root order and other root kinds while emitting typed - degradation through the diagnostic owner introduced by #83. - -Confirmed scope: - -- Raw 32/64-bit file section and containing-segment coordinates. -- Regular Mach-O, dyld concatenated-file, and cache subfile/local offset - semantics. -- Whole pointer-table and per-entry referenced-layout validation. -- Additive Diagnostics SPI file-root aggregate and legacy property parity. -- PrivateHeaderKit file-mode root diagnostic ingestion through the existing - bounded member channel. - -Required invariants: - -- Reuse #83's neutral table reader, checked coordinate owner, entry/byte - budgets, and `ObjCMetadataTableDiagnostic`; add no parallel budget or report. -- Absent/wrong-bitness is `nil` without a diagnostic; a legal empty section is - `[]`; a malformed table is empty plus one table diagnostic; a malformed entry - is omitted with an indexed diagnostic while later siblings remain ordered. -- Existing twelve file root properties keep their signatures and project the - checked result; `ObjCSectionRepresentable` gains no requirement. -- Loaded roots, regular member tables, RW-extension arrays, loaded image-info, - and C-string hardening are outside #88. - -Validation gate: - -- Deterministic 32/64 regular-file boundary, truncation, coordinate overflow, - budget/remainder, and good/bad/good fixtures. -- Deterministic cache/subfile coordinate fixture or an equivalent targeted - contract test at the offset owner. -- #60, #65, #79, #83 regressions; Debug/Release and Apple cross-builds. -- Exact MachOObjCSection → MachOSwiftSection → PrivateHeaderKit pin coherence. -- PrivateHeaderKit full tests, release-script tests, codex-review, Ready PR, - GitHub review/CI, then merge to `main`. - -Status: - -- Design gate approved: - - add Diagnostics SPI `ObjCFileRootReadResult` and - `MachOFile.ObjectiveC.readRoots()` with the twelve existing root values and - ordered table diagnostics; - - use neutral `ObjCMetadataTableDiagnostic.RootSection` as the vocabulary, - preserving `LoadedImageRootSection` and `FileRootSection` as source aliases; - - add `.fileRoot(section:pointerWidth:)` without changing the loaded owner; - - find raw `Section64`/`SegmentCommand64` or 32-bit equivalents together and - validate coordinates without existential getters; - - derive one canonical logical field offset: ordinary section file offset, or - cache section address minus main-cache shared-region start; - - resolve physical backing only through `fileHandleAndOffset(forOffset:)`, - which adds an ordinary fat-slice header offset or maps to the correct cache - subfile-local offset; - - for every nonempty file-backed section, including cache images, require raw - section file offset to equal the segment-mapped offset; allow a legal - zero-size coalesced section to succeed before that equality or any backing - lookup; - - retain the shared count/byte budgets and per-entry checked resolver, and - make all legacy root properties projections of their targeted checked read. -- A read-only survey of 6,288 Objective-C root sections in the current macOS - shared cache found zero nonempty file/VM offset mismatches. General Mach-O and - dyld-cache address conversion owners remain unchanged; #88 is isolated to the - file-root boundary. -- MachOObjCSection checkpoint - `6a63b4fd7950ab5a61502047070d3ff075011108` adds the file-root aggregate, - twelve compatibility projections, typed section/segment discovery, bounded - root and referenced-layout reads, Diagnostics SPI cases, and 32/64-bit - deterministic fixtures. Checkpoint - `15f727003bf031b300dff1f92fb57a6cdf01d282` moves file/loaded roots onto one - neutral root table/pointer owner and pins zero-size and mapping-failure - precedence. -- A temporary probe against the iOS 27 beta `24A5390f` shared cache found - TrialProto's nonempty `__objc_classlist` in subcache `.01`: canonical logical - offset `0x845e39e8` resolved through `fileHandleAndOffset(forOffset:)` to - physical-local `0x6f279e8`, matching `cacheAndFileOffset`. `readRoots()` - returned 226 classes and zero diagnostics. The probe was removed completely; - deterministic tests retain the logical-domain and backing-boundary contracts. -- Final MachOObjCSection cohort commit - `8f0ff76f02c0865422a72662177b5e687e43522d` passed 124 focused regressions, - Debug/Release and Apple cross-builds, the real cache probe, independent audit, - and codex-review with no findings. -- MachOSwiftSection cohort commit - `06ed57ab39fc24956f9079beeb407fffa30d50f4` pins that exact reader. Its six - ObjC-ancestor tests and Release product build passed; codex-review job - `F6B1C8EF-F779-4871-A779-93A953F9FED1` found no issue. -- PrivateHeaderKit now consumes `readRoots()` for file-backed images, retains - file-root diagnostics in the existing bounded report, pins both cohort SHAs, - and covers the wire mapping with a malformed 64-bit class-list fixture. - Swift 6.3.2 ran 625 tests successfully; the macOS Release build, - release-script contracts, Swift 6.3.2 iOS/watchOS Core and test cross-builds, - and both simulator-helper Release cross-builds passed. An independent - consumer audit found no P1/P2 issue. -- Final branch-wide codex-review against `main` found no issue (job - `0628D06C-89D9-4A26-9079-DA2252DDEEAA`). Issue #88 is ready for delivery; - remove this temporary ledger before opening the PR.