Repository: crytic/slither

Issue:
[Bug]: Combining using-for and this breaks IR generation 
### Describe the issue:

When I use a library for a contract and then invoke a library function using the `this` reference, IR generation breaks.

### Code example to reproduce the issue:
```
library Lib {
  function f(Hello h) external {

  }
}

contract Hello {
    using Lib for Hello;

    function test() external {
      this.f();
    }
}
```
### Version:

0.9.6

### Relevant log output:

```shell
ERROR:ConvertToIR:Function not found f
ERROR:ContractSolcParsing:Impossible to generate IR for Hello.test (test.sol#12-14):
 'NoneType' object has no attribute 'type'
INFO:Printers:Contract Lib
        Function Lib.f(Hello) (*)
Contract Hello
        Function Hello.test() (*)
                Expression: this.f()
                IRs:
```



Discussion:

Resolving patch:
diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py
--- a/slither/slithir/convert.py
+++ b/slither/slithir/convert.py
@@ -630,6 +630,17 @@ def propagate_types(ir: Operation, node: "Node"):  # pylint: disable=too-many-lo
                     if new_ir:
                         return new_ir
 
+                # convert library function when used with "this"
+                if (
+                    isinstance(t, ElementaryType)
+                    and t.name == "address"
+                    and ir.destination.name == "this"
+                    and UserDefinedType(node_function.contract) in using_for
+                ):
+                    new_ir = convert_to_library_or_top_level(ir, node, using_for)
+                    if new_ir:
+                        return new_ir
+
                 if isinstance(t, UserDefinedType):
                     # UserdefinedType
                     t_type = t.type
@@ -1564,6 +1575,18 @@ def convert_to_library_or_top_level(
         if new_ir:
             return new_ir
 
+    if (
+        isinstance(t, ElementaryType)
+        and t.name == "address"
+        and ir.destination.name == "this"
+        and UserDefinedType(node.function.contract) in using_for
+    ):
+        new_ir = look_for_library_or_top_level(
+            contract, ir, using_for, UserDefinedType(node.function.contract)
+        )
+        if new_ir:
+            return new_ir
+
     return None
 
 


Test patch:
diff --git a/tests/e2e/solc_parsing/test_ast_parsing.py b/tests/e2e/solc_parsing/test_ast_parsing.py
--- a/tests/e2e/solc_parsing/test_ast_parsing.py
+++ b/tests/e2e/solc_parsing/test_ast_parsing.py
@@ -448,6 +448,7 @@ def make_version(minor: int, patch_min: int, patch_max: int) -> List[str]:
     Test("using-for-functions-list-3-0.8.0.sol", ["0.8.15"]),
     Test("using-for-functions-list-4-0.8.0.sol", ["0.8.15"]),
     Test("using-for-global-0.8.0.sol", ["0.8.15"]),
+    Test("using-for-this-contract.sol", ["0.8.15"]),
     Test("library_event-0.8.16.sol", ["0.8.16"]),
     Test("top-level-struct-0.8.0.sol", ["0.8.0"]),
     Test("yul-top-level-0.8.0.sol", ["0.8.0"]),
diff --git a/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip b/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip
new file mode 100644
Binary files /dev/null and b/tests/e2e/solc_parsing/test_data/compile/using-for-this-contract.sol-0.8.15-compact.zip differ
diff --git a/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json
new file mode 100644
--- /dev/null
+++ b/tests/e2e/solc_parsing/test_data/expected/using-for-this-contract.sol-0.8.15-compact.json
@@ -0,0 +1,8 @@
+{
+  "Lib": {
+    "f(Hello)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n}\n"
+  },
+  "Hello": {
+    "test()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n"
+  }
+}
\ No newline at end of file
diff --git a/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol
new file mode 100644
--- /dev/null
+++ b/tests/e2e/solc_parsing/test_data/using-for-this-contract.sol
@@ -0,0 +1,13 @@
+library Lib {
+  function f(Hello h) external {
+
+  }
+}
+contract Hello {
+    using Lib for Hello;
+
+    function test() external {
+      this.f();
+    }
+}
+