Skip to content

Commit c35de5d

Browse files
authored
Merge pull request #110 from rockbruno/emojis
Fix emojis breaking obfuscation
2 parents 12b281b + ab40790 commit c35de5d

5 files changed

Lines changed: 73 additions & 6 deletions

File tree

‎SOURCEKITISSUES.md‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ These are problems that SourceKit has that are unrelated to a specific feature,
2020
**Note: You can use the `--ignore-targets` argument to completely disable the obfuscation of specific targets.**
2121

2222
- (SR-9020)](https://bugs.swift.org/browse/SR-9020) Legacy KeyPaths that include types (like `#keyPath(Foo.bar)`) will not get indexed.
23-
- Any file that has an emoji will break the obfuscation process. This may not be a SourceKit bug itself, but something that we have to treat on our side.
2423
- `@objc optional` protocol methods don't have their references indexed.
2524

2625
# Additional important information

‎Sources/SwiftShieldCore/Obfuscator/SourceKitObfuscator.swift‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,27 +199,28 @@ extension SourceKitObfuscator {
199199
// Avoid duplicates.
200200
currentReferenceIndex += 1
201201
}
202+
let currentCharacter = charArray[currentCharIndex]
202203
if line == reference.line, column == reference.column {
203204
previousReference = reference
204205
let originalName = reference.name
205206
let obfuscatedName = obfuscate(name: originalName)
206-
let wasInternalKeyword = charArray[currentCharIndex] == "`"
207+
let wasInternalKeyword = currentCharacter == "`"
207208
for i in 1 ..< (originalName.count + (wasInternalKeyword ? 2 : 0)) {
208209
charArray[currentCharIndex + i] = ""
209210
}
210211
charArray[currentCharIndex] = obfuscatedName
211212
currentReferenceIndex += 1
212213
currentCharIndex += originalName.count
213-
column += originalName.count
214+
column += originalName.utf8Count
214215
if wasInternalKeyword {
215216
charArray[currentCharIndex] = ""
216217
}
217-
} else if charArray[currentCharIndex] == "\n" {
218+
} else if currentCharacter == "\n" {
218219
line += 1
219220
column = 1
220221
currentCharIndex += 1
221222
} else {
222-
column += 1
223+
column += currentCharacter.utf8Count
223224
currentCharIndex += 1
224225
}
225226
}

‎Sources/SwiftShieldCore/StringHelpers.swift‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,10 @@ extension NSTextCheckingResult {
6868
return groupStartIndex ..< groupEndIndex
6969
}
7070
}
71+
72+
extension String {
73+
/// Considers emoji scalars when counting.
74+
var utf8Count: Int {
75+
return utf8.count
76+
}
77+
}

‎Sources/swiftshield/main.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import SwiftShieldCore
44

55
struct Swiftshield: ParsableCommand {
66
static var configuration = CommandConfiguration(
7-
abstract: "SwiftShield 4.0.0",
7+
abstract: "SwiftShield 4.0.1",
88
subcommands: [Obfuscate.self, Deobfuscate.self]
99
)
1010
}

‎Tests/SwiftShieldTests/FeatureTests.swift‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,64 @@ final class FeatureTests: XCTestCase {
188188
//}
189189
""")
190190
}
191+
192+
func test_files_withEmojis() throws {
193+
let (obfs, store, delegate) = baseTestData()
194+
let module = try testModule(withContents: """
195+
enum JSON {
196+
static func parse(_ a: String) -> String { return a }
197+
}
198+
199+
extension String {
200+
func unobfuscate() -> String { return self }
201+
}
202+
203+
func l3️⃣og(_ a: String) -> String { return JSON.parse("") }
204+
205+
var paramsString = "foo"
206+
207+
struct Logger {
208+
func log() {
209+
log("Hello 👨‍👩‍👧‍👧 3 A̛͚̖ 3️⃣ response up message 📲: \\(JSON.parse(paramsString.unobfuscate()).description) 🇹🇩👫👨‍👩‍👧‍👧👨‍👨‍👦"); log("")
210+
}
211+
212+
func log(_ a: String) {
213+
_ = l3️⃣og("foo".unobfuscate())
214+
}
215+
}
216+
""")
217+
store.obfuscationDictionary["JSON"] = "OBS1"
218+
store.obfuscationDictionary["parse"] = "OBS2"
219+
store.obfuscationDictionary["unobfuscate"] = "OBS3"
220+
store.obfuscationDictionary["log"] = "OBS4"
221+
store.obfuscationDictionary["Logger"] = "OBS5"
222+
store.obfuscationDictionary["l3️⃣og"] = "OBS6"
223+
224+
try obfs.registerModuleForObfuscation(module)
225+
try obfs.obfuscate()
226+
227+
XCTAssertEqual(delegate.receivedContent[modifiableFilePath], """
228+
enum OBS1 {
229+
static func OBS2(_ a: String) -> String { return a }
230+
}
231+
232+
extension String {
233+
func OBS3() -> String { return self }
234+
}
235+
236+
func OBS6(_ a: String) -> String { return OBS1.OBS2("") }
237+
238+
var paramsString = "foo"
239+
240+
struct OBS5 {
241+
func OBS4() {
242+
OBS4("Hello 👨‍👩‍👧‍👧 3 A̛͚̖ 3️⃣ response up message 📲: \\(OBS1.OBS2(paramsString.OBS3()).description) 🇹🇩👫👨‍👩‍👧‍👧👨‍👨‍👦"); OBS4("")
243+
}
244+
245+
func OBS4(_ a: String) {
246+
_ = OBS6("foo".OBS3())
247+
}
248+
}
249+
""")
250+
}
191251
}

0 commit comments

Comments
 (0)