-
-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exclude files or code from obfuscation #31
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks interesting! I have a few questions:
- What
-ignore-files
is doing is ignore registering a symbol if the name matches the name of an "ignored file", did you mean to ignore files completely? If so, is there a reason to do so? That would only compile correctly if your file doesn't reference anything from other files. - Ignoring specific symbols is great, but prefixes and suffixes sounds like something super specific that people wouldn't normally do, what if we made a single
-ignore-symbols
instead?
Some new tests would also be great 🙂 |
There is two solution came to my mind :
What do you recommend?
|
You can retrieve access control - I don't have it from the top of my head but if you use |
Also why static properties are not obfuscated?
the xx..xx is my property name, but it's not obfuscated. It seems a problem with |
Can you run your code with |
{removed large output} |
|
Sorry, it's actually
|
{removed large output} |
Can you move this output to a pastebin or something like that so this page doesn't get cluttered? you only check for |
Thank you! |
@rockbruno @vrujbr please check the edited files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! I haven't tested it yet but the shape of it looks exactly like we need 🙂 I'll just nitpick the structure of the code:
@@ -97,6 +96,20 @@ class AutomaticSwiftShield: Protector { | |||
} | |||
writeToFile(data: data, path: path, info: "Automatic mode for \(path)") | |||
} | |||
|
|||
func removeSuffixTags() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand what this is supposed to be doing, is it a leftover from something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover, I will remove it.
let filesToIgnore: Set<String> | ||
let excludedPrefixTag: String | ||
let excludedSuffixTag: String | ||
var publicProtocols: Set<String>! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not use force unwrap - If storing the protocols here are needed, we can pre-init it for safety reasons 🙂
var publicProtocols: Set<String> = []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
|
||
if self.excludedSuffixTag != "" && name.hasSuffix(excludedSuffixTag) { | ||
return nil | ||
if excludePublic { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid making getNameData
get super big, we can move this logic to a separate shouldIgnoreSymbol()
-like method, makes sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
let attributesData = dict.getAttributes(dict: attributesDict, subKey: sourceKit.attributeID) | ||
|
||
|
||
//Check if variant is public |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's avoid comments unless explaining an intent is needed - what is happening should be clear enough through the name of the properties we're dealing with.
|
||
//Check if variant is public | ||
let isPublic = attributesData.filter { item in | ||
return item.contains("public") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would avoid dealing with strings directly. We can make an enum to handle visibility identifiers. I already did that for kinds, so we can follow the same pattern 🙂
}.count != 0 | ||
|
||
//Add to publicProtocols array | ||
if kind == "source.lang.swift.decl.protocol" && isPublic { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here (not dealing with strings directly), SKAPI already has a method to return what an identifier is - I think we just need to add the protocol case.
|
||
//Handle public protocol's functions | ||
for protocolName in publicProtocols { | ||
if usr.contains(protocolName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understood this correctly, shouldn't this be simply publicProtocols.contains(usr)
instead of a loop? This is running in O(nˆ2)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because the receiver_usr
isn't returning just a name, It's something like that
s:17ObfuscationSource14ViewControllerC5countSivp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now. The problem is that using contains
inside an usr will likely not work in a bigger app because nothing stops other modules from having private protocols with the same name as your public one. I think you need to store the protocol usrs in publicProtocols
instead of their names to avoid this loop.
But I'm getting some bad vibes, is this deterministic? I'm having the impression that a public protocol's method would be wrongly obfuscated if the order of the files changed. If you look at isReferencingInternal()
, I had to even make it recursive to make it work. Things are slightly more difficult here because it happens before everything, but I think it's gonna work nicely in the end.
guard let protected = obfuscationData.obfuscationDict[name] else { | ||
//if !shouldRemoveSuffixTags { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove these leftovers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove it.
@@ -57,4 +55,9 @@ protector.protectStoryboards(data: obfuscationData) | |||
protector.writeToFile(data: obfuscationData) | |||
protector.markProjectsAsProtected() | |||
Logger.log(.finished) | |||
|
|||
if automatic && CommandLine.arguments.contains("-clear-suffix-tags") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's also a leftover right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover, I will remove it.
|
||
var data = [String]() | ||
|
||
let _ = SKApi.sourcekitd_variant_array_apply(dict) { (_, attributesDict) in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this safe? Wouldn't it crash on none-array dict
?
I took this weekend to run the property obfuscation feature (and to implement the public-ignoring myself to see if I could do it) to see if there no hidden problems in it, and I found a couple 😢 In regards to obfuscating properties, it turns out that it really messes up Regarding avoiding publics, I tried to do it and faced many problems, including some we haven't noticed before, which is that
SourceKit isn't very helpful here since it does not mark I would deeply investigate all these edge cases before trying to develop this again, but I still believe it's possible. I unfortunately do not know what to do in regards to properties though. |
Great work @rockbruno! To these edge cases.. |
case "var.instance", | ||
"var.static", | ||
"var.class": | ||
return .property | ||
case "function.free", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you enable property, confirm no storyboard property in use
Any update on this? Is there any plan for the future for ignoring public methods? |
My previous comment still holds true, SourceKit doesn't cover all ways to make something public and things that are derived need to be ignored, so I don't have a good outlook for this 😢 |
The tool has been remade. SDK mode exists, and although the bugs weren't fixed, we detailed them in the section. The exclusion part can still be done. |
In this PR :
1 - Exclude files from obfuscation using
-ignore-files
(please not this will only obfuscate the class/struct.. name).2 - Exclude properties/variables/classes.. that start with a tag using
excluded-prefix-tag
.3 - Exclude properties/variables/classes.. that end with a tag using
excluded-suffix-tag
.4 - Enable properties obfuscations.