Skip to content

C#: Better handing of extension methods and extension blocks#514

Merged
maciejpirog merged 2 commits intomainfrom
mpir/csharp-extension-methods-and-blocks
Dec 31, 2025
Merged

C#: Better handing of extension methods and extension blocks#514
maciejpirog merged 2 commits intomainfrom
mpir/csharp-extension-methods-and-blocks

Conversation

@maciejpirog
Copy link
Contributor

@maciejpirog maciejpirog commented Dec 30, 2025

Extension methods

In C# some function parameters are not real parameters, in particular this parameters in extension methods. Such a method can be defined as:

void foo(this string s, int a) { }

It is, in fact, a single-argument method on the string class, which can later be called as val.foo(123). To better handle definitions of such extension methods and extension blocks, we:

  • make it match function definition with arguments without the artificial this arguments, e.g. the definition above will be matched by patterns:
    • $T $F($PT $PN, int a) { ... }
    • $T $F(this $PT $PN, int a) { ... }
    • $T $F(int a) { ... }

Extension blocks

There is a syntactic sugar for extension methods: extension blocks. The code

public static class C
{
  extension(string s)
  {
    public string InQuotes()
    {
      return "\"" + s + "\"";
    }
  }
}

is equivalent to

public static class C
{
  public string InQuotes(this string s)
  {
    return "\"" + s + "\"";
  }
}

There is no good way to express such a block in Generic AST and we want to be able to do taint analysis with the string s above treated as source. Hence, in this PR, we translate extension blocks to a bunch of extension methods. This way, we can write a rule such as:

rules:
  - id: extension_taint
    message: "extension taint test"
    languages:
      - csharp
    severity: ERROR
    mode: taint
    pattern-sources:
      - patterns:
        - pattern-inside: |
            $RET $FUNC(this string $PARAM, ...) { ... }
        - focus-metavariable: $PARAM
    pattern-sinks:
      - patterns:
          - pattern: |
              sink(s)

And it will match the following:

public static class C
{
    // in an extension block:
    
    // in the rule, we assume that the extended string is tainted
    extension(string s)
    {
        void foo1(int aaaa){
            // ruleid: extension_taint
            sink(s);
        }
        
        void foo2(){
            // ok:
            sink(t);
        }
        
        void foo3(){
            // ruleid: extension_taint
            sink(s);
        }
        
        // ruleid: extension_taint
        public string Prop2 => sink(s);

        public string Prop
        {
            // ruleid: extension_taint
            get => sink(s);
            // ruleid: extension_taint
            set => sink(s);
        }
    }

    // standalone:

    public void foo4(this string s)
    {
      // ruleid: extension_taint
      sink(s);
    }
    
}

Future work

  • At the moment we cannot match extensions block as separate units, we have to write class $C { ... extension ($T $V) { ... } ... } which might be imprecise for more complicated matching rules.

  • For extension blocks, if we want to say the entire object is tainted, we show the source of taint in the dataflow trace to be the method itself, not the string s in the line that contains extension(string s).

@maciejpirog maciejpirog force-pushed the mpir/csharp-extension-methods-and-blocks branch from b25fe6d to 66f240b Compare December 30, 2025 23:09
Copy link
Collaborator

@dimitris-m dimitris-m left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a test in tests/patterns/csharp/ to make sure this is recorded:

At the moment we cannot match extensions block as separate units, we have to write class $C { ... extension ($T $V) { ... } ... } which might be imprecise for more complicated matching rules.

@dimitris-m dimitris-m removed the request for review from willem-delbare December 30, 2025 23:42
@maciejpirog maciejpirog force-pushed the mpir/csharp-extension-methods-and-blocks branch from 66f240b to d70d18f Compare December 30, 2025 23:47
@maciejpirog maciejpirog force-pushed the mpir/csharp-extension-methods-and-blocks branch from d70d18f to 8bbce6e Compare December 31, 2025 00:37
@maciejpirog maciejpirog merged commit 5ec3e60 into main Dec 31, 2025
6 checks passed
@maciejpirog maciejpirog deleted the mpir/csharp-extension-methods-and-blocks branch December 31, 2025 00:56
@maciejpirog maciejpirog mentioned this pull request Dec 31, 2025
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jan 9, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [opengrep/opengrep](https://github.com/opengrep/opengrep) | minor | `v1.13.2` → `v1.14.1` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>opengrep/opengrep (opengrep/opengrep)</summary>

### [`v1.14.1`](https://github.com/opengrep/opengrep/releases/tag/v1.14.1): Opengrep 1.14.1

[Compare Source](opengrep/opengrep@v1.14.0...v1.14.1)

#### Improvements

- Clojure translation part II by [@&#8203;dimitris-m](https://github.com/dimitris-m) in [#&#8203;517](opengrep/opengrep#517)
- C#: Allow implicit variables in properties to be taint sources by [@&#8203;maciejpirog](https://github.com/maciejpirog) in [#&#8203;516](opengrep/opengrep#516)
- Add core flags `dump_rule` and `dump_patterns_of_rule` as options in the show command by [@&#8203;maciejpirog](https://github.com/maciejpirog) in [#&#8203;519](opengrep/opengrep#519)

#### Bug fixes

- Fix: pass signature databaseb to lambda analysis, handle method mutation tainting by [@&#8203;corneliuhoffman](https://github.com/corneliuhoffman) in [#&#8203;520](opengrep/opengrep#520)

#### Tech debt

- Fix CHANGELOG.md, OPENGREP.md, remove unused files by [@&#8203;dimitris-m](https://github.com/dimitris-m) in [#&#8203;523](opengrep/opengrep#523)

**Full Changelog**: <opengrep/opengrep@v1.14.0...v1.14.1>

### [`v1.14.0`](https://github.com/opengrep/opengrep/releases/tag/v1.14.0): Opengrep 1.14.0

[Compare Source](opengrep/opengrep@v1.13.2...v1.14.0)

#### Improvements

- Support for higher-order functions in intrafile taint analysis by [@&#8203;corneliuhoffman](https://github.com/corneliuhoffman) in [#&#8203;469](opengrep/opengrep#469) and [#&#8203;513](opengrep/opengrep#513)
- Clojure: Improved support for Clojure (incl. tainting) by [@&#8203;dimitris-m](https://github.com/dimitris-m) in [#&#8203;501](opengrep/opengrep#501)
- Dart: Improved support for Dart by [@&#8203;maciejpirog](https://github.com/maciejpirog) in [#&#8203;508](opengrep/opengrep#508)
- C#: Better handing of extension methods and extension blocks by [@&#8203;maciejpirog](https://github.com/maciejpirog) in [#&#8203;514](opengrep/opengrep#514)

#### Fixes

- Bump cygwin install action by [@&#8203;dimitris-m](https://github.com/dimitris-m) in [#&#8203;503](opengrep/opengrep#503) and [#&#8203;509](opengrep/opengrep#509)

**Full Changelog**: <opengrep/opengrep@v1.13.2...v1.14.0>

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi42OS4yIiwidXBkYXRlZEluVmVyIjoiNDIuNjkuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90IiwiYXV0b21hdGlvbjpib3QtYXV0aG9yZWQiLCJkZXBlbmRlbmN5LXR5cGU6Om1pbm9yIl19-->
@dimitris-m dimitris-m added the lang Add or improve language support label Jan 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lang Add or improve language support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants