Semgrep: Is it possible to match a function based on its body, instead of its name?

834 Views Asked by At

The question is in the title.

As an example, say I am interested in catching all calls of functions that use a certain global variable (foo here).

I tried the following:

rules:
  - id: dont-call-functions-using-foo
    message: "don't call functions using `foo`"
    languages: [ javascript ]
    severity: ERROR
    patterns:
        - pattern: $FUNCTION(...)
        - patterns:
          - pattern-inside: |
              $FUNCTION(...) {
                ...
              }
          - pattern: bar

On the following JavaScript file:

const foo = "GLOBAL";

function bar() { console.log(foo); }
function baz() { console.log("hello"); }

// I would like this to be reported
bar()
// ... but not this
baz()

Sadly, this does not work:

$ semgrep -c test.yaml test.js
Running 1 rules...
ran 1 rules on 1 files: 0 findings

I think I "understand" why my rule is not correct: It looks for a pattern that is both a function definition and a function call; And it does not "correlate" two distinct code locations.

I came to believe that what I am trying to achieve is impossible without the join mode, but I am quite a beginner with semgrep, and would be happy to be proven wrong.

1

There are 1 best solutions below

0
On

Beginner too, and rule below matches.

Rule

Try on playground

rules:
  - id: dont-call-functions-using-foo
    message: don't call functions using `foo`
    languages:
      - javascript
    severity: ERROR
    patterns:
      - pattern: |
          const $X = ...
          ...
          function $FUNC() { $FUNCA($X) }
          ...
          $FUNC()
      - pattern: $FUNC()

Or if you want to find where foo is used

Try on playground

rules:
  - id: dont-call-functions-using-foo
    message: "don't call functions using `foo`"
    languages: [ javascript ]
    severity: ERROR
    patterns:
        - patterns:
          - pattern-inside: |
              function $FUNCTION(...) {
                ...
              }
          - pattern: foo