Skip to content

Commit

Permalink
Merge pull request #110 from rockbruno/emojis
Browse files Browse the repository at this point in the history
Fix emojis breaking obfuscation
  • Loading branch information
rockbruno authored May 18, 2020
2 parents 12b281b + ab40790 commit c35de5d
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 6 deletions.
1 change: 0 additions & 1 deletion SOURCEKITISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ These are problems that SourceKit has that are unrelated to a specific feature,
**Note: You can use the `--ignore-targets` argument to completely disable the obfuscation of specific targets.**

- (SR-9020)](https://bugs.swift.org/browse/SR-9020) Legacy KeyPaths that include types (like `#keyPath(Foo.bar)`) will not get indexed.
- 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.
- `@objc optional` protocol methods don't have their references indexed.

# Additional important information
Expand Down
9 changes: 5 additions & 4 deletions Sources/SwiftShieldCore/Obfuscator/SourceKitObfuscator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,27 +199,28 @@ extension SourceKitObfuscator {
// Avoid duplicates.
currentReferenceIndex += 1
}
let currentCharacter = charArray[currentCharIndex]
if line == reference.line, column == reference.column {
previousReference = reference
let originalName = reference.name
let obfuscatedName = obfuscate(name: originalName)
let wasInternalKeyword = charArray[currentCharIndex] == "`"
let wasInternalKeyword = currentCharacter == "`"
for i in 1 ..< (originalName.count + (wasInternalKeyword ? 2 : 0)) {
charArray[currentCharIndex + i] = ""
}
charArray[currentCharIndex] = obfuscatedName
currentReferenceIndex += 1
currentCharIndex += originalName.count
column += originalName.count
column += originalName.utf8Count
if wasInternalKeyword {
charArray[currentCharIndex] = ""
}
} else if charArray[currentCharIndex] == "\n" {
} else if currentCharacter == "\n" {
line += 1
column = 1
currentCharIndex += 1
} else {
column += 1
column += currentCharacter.utf8Count
currentCharIndex += 1
}
}
Expand Down
7 changes: 7 additions & 0 deletions Sources/SwiftShieldCore/StringHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,10 @@ extension NSTextCheckingResult {
return groupStartIndex ..< groupEndIndex
}
}

extension String {
/// Considers emoji scalars when counting.
var utf8Count: Int {
return utf8.count
}
}
2 changes: 1 addition & 1 deletion Sources/swiftshield/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import SwiftShieldCore

struct Swiftshield: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "SwiftShield 4.0.0",
abstract: "SwiftShield 4.0.1",
subcommands: [Obfuscate.self, Deobfuscate.self]
)
}
Expand Down
60 changes: 60 additions & 0 deletions Tests/SwiftShieldTests/FeatureTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,64 @@ final class FeatureTests: XCTestCase {
//}
""")
}

func test_files_withEmojis() throws {
let (obfs, store, delegate) = baseTestData()
let module = try testModule(withContents: """
enum JSON {
static func parse(_ a: String) -> String { return a }
}
extension String {
func unobfuscate() -> String { return self }
}
func l3️⃣og(_ a: String) -> String { return JSON.parse("") }
var paramsString = "foo"
struct Logger {
func log() {
log("Hello 👨‍👩‍👧‍👧 3 A̛͚̖ 3️⃣ response up message 📲: \\(JSON.parse(paramsString.unobfuscate()).description) 🇹🇩👫👨‍👩‍👧‍👧👨‍👨‍👦"); log("")
}
func log(_ a: String) {
_ = l3️⃣og("foo".unobfuscate())
}
}
""")
store.obfuscationDictionary["JSON"] = "OBS1"
store.obfuscationDictionary["parse"] = "OBS2"
store.obfuscationDictionary["unobfuscate"] = "OBS3"
store.obfuscationDictionary["log"] = "OBS4"
store.obfuscationDictionary["Logger"] = "OBS5"
store.obfuscationDictionary["l3️⃣og"] = "OBS6"

try obfs.registerModuleForObfuscation(module)
try obfs.obfuscate()

XCTAssertEqual(delegate.receivedContent[modifiableFilePath], """
enum OBS1 {
static func OBS2(_ a: String) -> String { return a }
}
extension String {
func OBS3() -> String { return self }
}
func OBS6(_ a: String) -> String { return OBS1.OBS2("") }
var paramsString = "foo"
struct OBS5 {
func OBS4() {
OBS4("Hello 👨‍👩‍👧‍👧 3 A̛͚̖ 3️⃣ response up message 📲: \\(OBS1.OBS2(paramsString.OBS3()).description) 🇹🇩👫👨‍👩‍👧‍👧👨‍👨‍👦"); OBS4("")
}
func OBS4(_ a: String) {
_ = OBS6("foo".OBS3())
}
}
""")
}
}

0 comments on commit c35de5d

Please sign in to comment.