{"action":"created","issue":{"url":"https://api.github.com/repos/magic-lang/rock/issues/73","repository_url":"https://api.github.com/repos/magic-lang/rock","labels_url":"https://api.github.com/repos/magic-lang/rock/issues/73/labels{/name}","comments_url":"https://api.github.com/repos/magic-lang/rock/issues/73/comments","events_url":"https://api.github.com/repos/magic-lang/rock/issues/73/events","html_url":"https://github.com/magic-lang/rock/issues/73","id":174505252,"number":73,"title":"Obfuscator problem","user":{"login":"thomasfanell","id":12230189,"avatar_url":"https://avatars.githubusercontent.com/u/12230189?v=3","gravatar_id":"","url":"https://api.github.com/users/thomasfanell","html_url":"https://github.com/thomasfanell","followers_url":"https://api.github.com/users/thomasfanell/followers","following_url":"https://api.github.com/users/thomasfanell/following{/other_user}","gists_url":"https://api.github.com/users/thomasfanell/gists{/gist_id}","starred_url":"https://api.github.com/users/thomasfanell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomasfanell/subscriptions","organizations_url":"https://api.github.com/users/thomasfanell/orgs","repos_url":"https://api.github.com/users/thomasfanell/repos","events_url":"https://api.github.com/users/thomasfanell/events{/privacy}","received_events_url":"https://api.github.com/users/thomasfanell/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/magic-lang/rock/labels/help%20wanted","name":"help wanted","color":"159818"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":12,"created_at":"2016-09-01T11:59:09Z","updated_at":"2016-09-19T19:14:10Z","closed_at":null,"body":"## Introduction\r\n\r\n[Relevant code can be found here](https://github.com/thomasfanell/rock/tree/obfuscator-debug/source/rock/frontend/obfuscator)\r\n\r\nI am working on a built-in obfuscator and I'm having some issues with overridden functions in certain scenarios. The obfuscator is launched right after phase 2 (resolving and classification of modules) and it searches the syntax tree for targets by employing a visitor. When a match is found, it stores away the node for later processing (when the search is exhausted).\r\n\r\nIn the obfuscation phase, function declarations are replaced by their obfuscated version by means of\r\n`owner removeFunction(originalFunctionDecl)` and `owner addFunction(obfuscatedFunctionDecl)`, where `obfuscatedFunctionDecl := originalFunctionDecl clone(newName)`\r\n\r\n\r\nThe target collector will of course check for function calls that reference obfuscation targets and mark them to be updated [code](https://github.com/thomasfanell/rock/blob/obfuscator-debug/source/rock/frontend/obfuscator/TargetCollector.ooc#L191) . I currently do this by updating its `ref` and `name` properties: [code](https://github.com/thomasfanell/rock/blob/obfuscator-debug/source/rock/frontend/obfuscator/Obfuscator.ooc#L67)\r\n\r\n```\r\nfunctionCall setRef(obfuscatedFunctionDecl)\r\nfunctionCall setName(obfuscatedFunctionDecl name)\r\n```\r\n\r\nFinally, at end of the obfuscation phase, I launch a new resolving process: `Tinkerer new(buildParams) process(allModules)`. [code](https://github.com/thomasfanell/rock/blob/obfuscator-debug/source/rock/frontend/obfuscator/Obfuscator.ooc#L25)\r\n\r\n## Example code\r\nThe obfuscator is set to change `ABSTRACT_FUNCTION` to `OBFUSCATED_FUNCTION`\r\n\r\n```ooc\r\nINHERITENCE_BASE: abstract class {\r\n    ABSTRACT_FUNCTION: abstract func -> String\r\n}\r\n\r\nINHERITENCE_CHILD1: class extends INHERITENCE_BASE {\r\n    init: func\r\n    ABSTRACT_FUNCTION: override func -> String {\r\n        \"CHILD1\"\r\n    }\r\n}\r\n\r\nINHERITENCE_CHILD2: class extends INHERITENCE_BASE {\r\n    backend := INHERITENCE_CHILD1 new()\r\n    init: func\r\n    ABSTRACT_FUNCTION: override func -> String {\r\n        //\r\n        // This is the problem\r\n        //\r\n        this backend ABSTRACT_FUNCTION()\r\n    }\r\n}\r\n\r\nINHERITENCE_CHILD3: class extends INHERITENCE_BASE {\r\n    backend := INHERITENCE_CHILD1 new()\r\n    init: func\r\n    ABSTRACT_FUNCTION: override func -> String {\r\n        \"CHILD3\"\r\n    }\r\n}\r\n\r\nraise(INHERITENCE_CHILD1 new() ABSTRACT_FUNCTION() != \"CHILD1\", \"INHERITENCE_CHILD1.ABSTRACT_FUNCTION1\")\r\nraise(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION() != \"CHILD1\", \"INHERITENCE_CHILD2.ABSTRACT_FUNCTION2\")\r\nraise(INHERITENCE_CHILD3 new() ABSTRACT_FUNCTION() != \"CHILD3\", \"INHERITENCE_CHILD3.ABSTRACT_FUNCTION3\")\r\n```\r\n\r\nThis particular scenario gives the error:\r\n```\r\nerror No such function ABSTRACT_FUNCTION() for `INHERITENCE_CHILD2`\r\n        this ABSTRACT_FUNCTION()\r\n```\r\n\r\n## Pre-obfuscation print-out\r\nNote the addresses of each `ABSTRACT_FUNCTION` implementation.\r\n\r\n```\r\nClassDecl {\r\n\tClassDecl INHERITENCE_CHILD1Class\r\n\tname: INHERITENCE_CHILD1Class\r\n\t\tfunction count: 5\r\n            --snip---\r\n\t\t\t0x29afdd0 --- INHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String\r\n}\r\nClassDecl {\r\n\tClassDecl INHERITENCE_CHILD2Class\r\n\tname: INHERITENCE_CHILD2Class\r\n\t\tfunction count: 5\r\n\t\t\t--snip---\r\n\t\t\t0x2844ee0 --- INHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String\r\n}\r\nFunctionDecl {\r\n\tAddress: 0x29afdd0\r\n\tINHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String\r\n\towner: ClassDecl INHERITENCE_CHILD1\r\n}\r\nFunctionDecl {\r\n\tAddress: 0x2844ee0\r\n\tINHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String\r\n\towner: ClassDecl INHERITENCE_CHILD2\r\n}\r\nFunctionCall {\r\n\tthis backend ABSTRACT_FUNCTION()\r\n\tresolved: yes\r\n\tref score: 513\r\n\texpr: this backend\r\n\tref: 0x29afdd0 --- INHERITENCE_CHILD1 ABSTRACT_FUNCTION -> String\r\n}\r\nFunctionCall {\r\n\traise(__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION(), \"CHILD1\"), \"INHERITENCE_CHILD2.ABSTRACT_FUNCTION2\", null)\r\n\tresolved: yes\r\n\tref score: 2304\r\n\texpr: NULL\r\n\tref: 0x2758550 --- raise~assert(condition: Bool, message: String, origin: Class = null)\r\n}\r\nFunctionCall {\r\n\t__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION(), \"CHILD1\")\r\n\tresolved: yes\r\n\tref score: 1\r\n\texpr: NULL\r\n\tref: 0x2990660 --- __OP_NE_String_String__Bool(left: String, right: String) -> Bool\r\n}\r\nFunctionCall {\r\n\tINHERITENCE_CHILD2 new() ABSTRACT_FUNCTION()\r\n\tresolved: yes\r\n\tref score: 513\r\n\texpr: INHERITENCE_CHILD2 new()\r\n\tref: 0x2844ee0 --- INHERITENCE_CHILD2 ABSTRACT_FUNCTION -> String\r\n}\r\n```\r\nEach function call clearly hold the correct reference to the corresponding function declaration.\r\n\r\n## Post-obfuscation print-out\r\n```\r\nClassDecl {\r\n\tClassDecl INHERITENCE_CHILD1Class\r\n\tname: INHERITENCE_CHILD1Class\r\n\t\tfunction count: 5\r\n\t\t\t--snip---\r\n\t\t\t0x3b1ebb0 --- INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String\r\n}\r\nClassDecl {\r\n\tAddress: 0x2ca0240\r\n\tClassDecl INHERITENCE_CHILD2Class\r\n\tname: INHERITENCE_CHILD2Class\r\n\t\tfunction count: 5\r\n            --snip---\r\n\t\t\t0x3b1eaa0 --- INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String\r\n}\r\nFunctionDecl {\r\n\tAddress: 0x3b1ebb0\r\n\tINHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String\r\n\towner: ClassDecl INHERITENCE_CHILD1\r\n}\r\nFunctionDecl {\r\n\tAddress: 0x3b1eaa0\r\n\tINHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String\r\n\towner: ClassDecl INHERITENCE_CHILD2\r\n}\r\nFunctionCall {\r\n\tthis backend ABSTRACT_FUNCTION()\r\n\tresolved: no\r\n\tref score: -2147483648\r\n\texpr: this backend\r\n\tref: NULL\r\n}\r\nFunctionCall {\r\n\traise(__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION(), \"CHILD1\"), \"INHERITENCE_CHILD2.ABSTRACT_FUNCTION2\", null)\r\n\tresolved: yes\r\n\tref score: 2304\r\n\texpr: NULL\r\n\tref: 0x2758550 --- raise~assert(condition: Bool, message: String, origin: Class = null)\r\n}\r\nFunctionCall {\r\n\t__OP_NE_String_String__Bool(INHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION(), \"CHILD1\")\r\n\tresolved: yes\r\n\tref score: 1\r\n\texpr: NULL\r\n\tref: 0x2990660 --- __OP_NE_String_String__Bool(left: String, right: String) -> Bool\r\n}\r\nFunctionCall {\r\n\tINHERITENCE_CHILD2 new() OBFUSCATED_FUNCTION()\r\n\tresolved: yes\r\n\tref score: 1\r\n\texpr: INHERITENCE_CHILD2 new()\r\n\tref: 0x3b1eaa0 --- INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String\r\n}\r\n```\r\nHere, the function call `this backend ABSTRACT_FUNCTION()` is somehow losing its reference (it should point to `INHERITENCE_CHILD1 OBFUSCATED_FUNCTION`), and the resolver is not able to find it. However, in the last function call, the reference to `OBFUSCATED_FUNCTION` is correctly maintained.\r\n\r\n\r\nI have verified that the reference is valid just before updating the function call reference:\r\n```\r\nCall: INHERITENCE_CHILD1 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String\r\nCall: this backend ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD1 OBFUSCATED_FUNCTION -> String\r\nCall: INHERITENCE_CHILD2 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD2 OBFUSCATED_FUNCTION -> String\r\nCall: INHERITENCE_CHILD3 new() ABSTRACT_FUNCTION() --- Ref: INHERITENCE_CHILD3 OBFUSCATED_FUNCTION -> String\r\n```\r\n\r\nI have tried resetting various score and state values in the relevant nodes, but this does not seem to help. Is there something else I need to do to correctly re-link function calls to the obfuscated references? Maybe I am going about this the wrong way?\r\n\r\nI am hoping that someone that have more intimate knowledge of the AST and resolving process will throw me a bone. @shamanas @vendethiel @zhaihj perhaps?"},"comment":{"url":"https://api.github.com/repos/magic-lang/rock/issues/comments/248093132","html_url":"https://github.com/magic-lang/rock/issues/73#issuecomment-248093132","issue_url":"https://api.github.com/repos/magic-lang/rock/issues/73","id":248093132,"user":{"login":"thomasfanell","id":12230189,"avatar_url":"https://avatars.githubusercontent.com/u/12230189?v=3","gravatar_id":"","url":"https://api.github.com/users/thomasfanell","html_url":"https://github.com/thomasfanell","followers_url":"https://api.github.com/users/thomasfanell/followers","following_url":"https://api.github.com/users/thomasfanell/following{/other_user}","gists_url":"https://api.github.com/users/thomasfanell/gists{/gist_id}","starred_url":"https://api.github.com/users/thomasfanell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thomasfanell/subscriptions","organizations_url":"https://api.github.com/users/thomasfanell/orgs","repos_url":"https://api.github.com/users/thomasfanell/repos","events_url":"https://api.github.com/users/thomasfanell/events{/privacy}","received_events_url":"https://api.github.com/users/thomasfanell/received_events","type":"User","site_admin":false},"created_at":"2016-09-19T19:14:10Z","updated_at":"2016-09-19T19:14:10Z","body":"@shamanas \r\n\r\nAs it turns out, omitting the clone calls only partially solved the problem, which of course means it didn't really solve the problem at all. As you say, there is something in the child nodes that is not taken into consideration by the obfuscator.\r\n\r\nWhen (if) you do come back, [obfuscator-v4](https://github.com/thomasfanell/rock/tree/obfuscator-v4) is the current branch I use for target practicing.\r\n\r\nThank you"}}
{"actor":{"display_login":"thomasfanell"}}