Skip to content

Commit

Permalink
Merge pull request #39 from ginsudev/fix/progress-crash
Browse files Browse the repository at this point in the history
Progress bar improvements, fixed a crash when applying fonts.
  • Loading branch information
ginsudev authored Jan 5, 2023
2 parents 28f70a1 + 1c6e83d commit 7c8be21
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 54 deletions.
12 changes: 12 additions & 0 deletions WDBFontOverwrite.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
4FE5EF3529653188003384EC /* FontMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE5EF3429653188003384EC /* FontMap.swift */; };
4FE5EF38296561A5003384EC /* FileEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE5EF37296561A5003384EC /* FileEditorView.swift */; };
4FE5EF3A296561B2003384EC /* FileEditorView.ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE5EF39296561B2003384EC /* FileEditorView.ViewModel.swift */; };
4FE5EF3E29664537003384EC /* ProgressManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE5EF3D29664537003384EC /* ProgressManager.swift */; };
C55CF774295BA37D000DE71C /* woff2_wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C55CF772295BA37D000DE71C /* woff2_wrapper.cpp */; };
C55CF776295BA9B1000DE71C /* BrotliPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55CF775295BA9B1000DE71C /* BrotliPadding.swift */; };
C55CF778295BAF42000DE71C /* libwoff2enc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C55CF76E295BA346000DE71C /* libwoff2enc.a */; };
Expand All @@ -36,6 +37,7 @@
4FE5EF3429653188003384EC /* FontMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontMap.swift; sourceTree = "<group>"; };
4FE5EF37296561A5003384EC /* FileEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileEditorView.swift; sourceTree = "<group>"; };
4FE5EF39296561B2003384EC /* FileEditorView.ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileEditorView.ViewModel.swift; sourceTree = "<group>"; };
4FE5EF3D29664537003384EC /* ProgressManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressManager.swift; sourceTree = "<group>"; };
C55CF76E295BA346000DE71C /* libwoff2enc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libwoff2enc.a; sourceTree = "<group>"; };
C55CF76F295BA346000DE71C /* libwoff2common.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libwoff2common.a; sourceTree = "<group>"; };
C55CF772295BA37D000DE71C /* woff2_wrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = woff2_wrapper.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -81,6 +83,14 @@
path = FileEditor;
sourceTree = "<group>";
};
4FE5EF3C2966452A003384EC /* Progress */ = {
isa = PBXGroup;
children = (
4FE5EF3D29664537003384EC /* ProgressManager.swift */,
);
path = Progress;
sourceTree = "<group>";
};
C55CF777295BAF42000DE71C /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -111,6 +121,7 @@
C5C9A7A72959351A00466D87 /* Info.plist */,
C5A95F45295964AE00C58FDB /* PreviewFonts */,
C5C9A7A22959341600466D87 /* RepackedFonts */,
4FE5EF3C2966452A003384EC /* Progress */,
4FE5EF362965617D003384EC /* FileEditor */,
C55CF775295BA9B1000DE71C /* BrotliPadding.swift */,
C5C9A7942959261000466D87 /* ContentView.swift */,
Expand Down Expand Up @@ -222,6 +233,7 @@
4FE5EF3A296561B2003384EC /* FileEditorView.ViewModel.swift in Sources */,
C5C9A7952959261000466D87 /* ContentView.swift in Sources */,
C55CF776295BA9B1000DE71C /* BrotliPadding.swift in Sources */,
4FE5EF3E29664537003384EC /* ProgressManager.swift in Sources */,
C5C9A7932959261000466D87 /* WDBFontOverwriteApp.swift in Sources */,
4FE5EF38296561A5003384EC /* FileEditorView.swift in Sources */,
C5C9A7AA2959417100466D87 /* vm_unaligned_copy_switch_race.c in Sources */,
Expand Down
15 changes: 6 additions & 9 deletions WDBFontOverwrite/ContentView.ViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ extension ContentView {
@Published var fontListSelection: Int = 0
@Published var customFontPickerSelection: Int = 0
@Published var message = "Choose a font."
@Published var progress: Progress!
@Published var importPresented: Bool = false
@Published var isPresentedFileEditor: Bool = false
@Published var importTTCRepackMode: TTCRepackMode = .woff2
Expand Down Expand Up @@ -105,14 +104,13 @@ extension ContentView {
guard selectedCustomFontType == .font else {
// Overwrite emoji
let emojiFont = FontMap.emojiCustomFont
overwriteWithCustomFont(
await overwriteWithCustomFont(
name: emojiFont.localPath,
targetPath: emojiFont.targetPath,
progress: progress
targetPath: emojiFont.targetPath
) {
self.progress = nil
self.message = $0
}
ProgressManager.shared.isBusy = false
return
}

Expand All @@ -126,16 +124,15 @@ extension ContentView {
for font in fonts {
let key = FontMap.key(forFont: font)
if let customFont = FontMap.fontMap[key] {
overwriteWithCustomFont(
await overwriteWithCustomFont(
name: customFont.localPath,
targetPath: customFont.targetPath,
progress: progress
targetPath: customFont.targetPath
) {
self.progress = nil
self.message = $0
}
}
}
ProgressManager.shared.isBusy = false
} catch {
print(error)
message = "Failed to read imported fonts."
Expand Down
22 changes: 12 additions & 10 deletions WDBFontOverwrite/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UniformTypeIdentifiers

struct ContentView: View {
@StateObject private var viewModel = ViewModel()
@StateObject private var progressManager = ProgressManager.shared
@Environment(\.openURL) private var openURL

var body: some View {
Expand Down Expand Up @@ -68,8 +69,12 @@ struct ContentView: View {
} else {
Text(viewModel.message)
}
if let progress = viewModel.progress {
ProgressView(progress)
if progressManager.isBusy {
ProgressView(
value: progressManager.completedProgress,
total: progressManager.totalProgress
)
.progressViewStyle(.linear)
}
}

Expand All @@ -78,13 +83,10 @@ struct ContentView: View {
ForEach(viewModel.fonts, id: \.name) { font in
Button {
viewModel.message = "Running"
viewModel.progress = Progress(totalUnitCount: 1)
overwriteWithFont(
name: font.repackedPath,
progress: viewModel.progress
) {
viewModel.message = $0
viewModel.progress = nil
Task {
await overwriteWithFont(name: font.repackedPath) {
viewModel.message = $0
}
}
} label: {
Text(font.name)
Expand Down Expand Up @@ -142,8 +144,8 @@ struct ContentView: View {
}
}
Button {
progressManager.isBusy = true
viewModel.message = "Running"
viewModel.progress = Progress(totalUnitCount: 1)
Task {
await viewModel.batchOverwriteFonts()
}
Expand Down
65 changes: 30 additions & 35 deletions WDBFontOverwrite/OverwriteFontImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,46 @@
import UIKit
import UniformTypeIdentifiers

func overwriteWithFont(name: String, progress: Progress, completion: @escaping (String) -> Void) {
func overwriteWithFont(name: String, completion: @escaping (String) -> Void) async {
let fontURL = Bundle.main.url(
forResource: name,
withExtension: nil,
subdirectory: "RepackedFonts"
)!
overwriteWithFont(

await overwriteWithFont(
fontURL: fontURL,
pathToTargetFont: "/System/Library/Fonts/CoreUI/SFUI.ttf",
progress: progress,
completion: completion
)
}

func overwriteWithFont(
fontURL: URL,
pathToTargetFont: String,
progress: Progress,
completion: ((String) -> Void)?
) {
DispatchQueue.global(qos: .userInteractive).async {
let succeeded = overwriteWithFontImpl(
fontURL: fontURL,
pathToTargetFont: pathToTargetFont,
progress: progress
)

print("done")

DispatchQueue.main.async {
completion?(succeeded ? "Success: force close an app to see results" : "Failed")
}
}
) async {
let succeeded = overwriteWithFontImpl(
fontURL: fontURL,
pathToTargetFont: pathToTargetFont
)

await MainActor.run(body: {
completion?(succeeded ? "Success: force close an app to see results" : "Failed")
})
}

/// Overwrite the system font with the given font using CVE-2022-46689.
/// The font must be specially prepared so that it skips past the last byte in every 16KB page.
/// See BrotliPadding.swift for an implementation that adds this padding to WOFF2 fonts.
func overwriteWithFontImpl(fontURL: URL, pathToTargetFont: String, progress: Progress) -> Bool {
func overwriteWithFontImpl(fontURL: URL, pathToTargetFont: String) -> Bool {
var fontData = try! Data(contentsOf: fontURL)
#if false
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[
0
].path
let documentDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask
)[0].path

let pathToTargetFont = documentDirectory + "/SFUI.ttf"
let pathToRealTargetFont = "/System/Library/Fonts/CoreUI/SFUI.ttf"
let origData = try! Data(contentsOf: URL(fileURLWithPath: pathToRealTargetFont))
Expand Down Expand Up @@ -103,16 +99,18 @@ func overwriteWithFontImpl(fontURL: URL, pathToTargetFont: String, progress: Pro
return false
}

// TODO(zhuowei): probably not the right way to use NSProgress...
let overwriteProgress = Progress(totalUnitCount: Int64(fontData.count))
progress.addChild(overwriteProgress, withPendingUnitCount: Int64(1))
DispatchQueue.main.async {
ProgressManager.shared.totalProgress = Double(fontData.count)
}

// for every 16k chunk, rewrite
print(Date())
for chunkOff in stride(from: 0, to: fontData.count, by: 0x4000) {
print(String(format: "%lx", chunkOff))
if chunkOff % 0x40000 == 0 {
overwriteProgress.completedUnitCount = Int64(chunkOff)
DispatchQueue.main.async {
ProgressManager.shared.completedProgress = Double(chunkOff)
}
}
// we only rewrite 16383 bytes out of every 16384 bytes.
let dataChunk = fontData[chunkOff..<min(fontData.count, chunkOff + 0x3fff)]
Expand All @@ -135,7 +133,9 @@ func overwriteWithFontImpl(fontURL: URL, pathToTargetFont: String, progress: Pro
}
print(Date())
print("successfully overwrote everything")
overwriteProgress.completedUnitCount = Int64(fontData.count)
DispatchQueue.main.async {
ProgressManager.shared.completedProgress = Double(fontData.count)
}
return true
}

Expand All @@ -152,9 +152,8 @@ func dumpCurrentFont() {
func overwriteWithCustomFont(
name: String,
targetPath: PathType?,
progress: Progress,
completion: ((String) -> Void)? = nil
) {
) async {
let documentDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask
Expand All @@ -165,24 +164,20 @@ func overwriteWithCustomFont(
completion?("No custom font imported")
return
}

print("b4 switch")

switch targetPath {
case .single(let path):
overwriteWithFont(
await overwriteWithFont(
fontURL: fontURL,
pathToTargetFont: path,
progress: progress,
completion: completion
)
case .many(let paths):
for path in paths {
if (access(path, F_OK) == 0) {
overwriteWithFont(
await overwriteWithFont(
fontURL: fontURL,
pathToTargetFont: path,
progress: progress,
completion: completion
)
}
Expand Down
15 changes: 15 additions & 0 deletions WDBFontOverwrite/Progress/ProgressManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// ProgressManager.swift
// WDBFontOverwrite
//
// Created by Noah Little on 5/1/2023.
//

import Foundation

final class ProgressManager: ObservableObject {
static let shared = ProgressManager()
var isBusy: Bool = false
@Published var completedProgress: Double = 0
@Published var totalProgress: Double = 0
}

0 comments on commit 7c8be21

Please sign in to comment.