Skip to content

Commit

Permalink
Metavariable Type Extension for Semgrep Rule Syntax 2.0 (#8184)
Browse files Browse the repository at this point in the history
This PR introduces the changes made in Semgrep rule syntax 1.0 to
version 2.0 as well.

fix #8183 

PR checklist:

- [ ] Purpose of the code is [evident to future
readers](https://semgrep.dev/docs/contributing/contributing-code/#explaining-code)
- [ ] Tests included or PR comment includes a reproducible test plan
- [ ] Documentation is up-to-date
- [ ] A changelog entry was [added to
changelog.d](https://semgrep.dev/docs/contributing/contributing-code/#adding-a-changelog-entry)
for any user-facing change
- [ ] Change has no security implications (otherwise, ping security
team)

If you're unsure about any of this, please see:

- [Contribution
guidelines](https://semgrep.dev/docs/contributing/contributing-code)!
- [One of the more specific guides located
here](https://semgrep.dev/docs/contributing/contributing/)
  • Loading branch information
ihji committed Jun 29, 2023
1 parent 3910610 commit 351e5a0
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 19 deletions.
30 changes: 30 additions & 0 deletions changelog.d/gh-8183.added
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
feat(rule syntax): Metavariable Type Extension for Semgrep Rule Syntax 2.0

This PR introduces the changes made in Semgrep rule syntax 1.0 to version 2.0 as well.

# rule syntax 2.0
rules:
- id: no-string-eqeq
message: find errors
severity: WARNING
languages:
- java
match:
all:
- not: null == (String $Y)
- $X == (String $Y)

# rule syntax 2.0 after proposed change
rules:
- id: no-string-eqeq
message: find errors
severity: WARNING
languages:
- java
match:
all:
- not: null == $Y
- $X == $Y
where:
- metavariable: $Y
type: String
57 changes: 38 additions & 19 deletions src/parsing/Parse_rule.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1043,16 +1043,14 @@ and parse_extra (env : env) (key : key) (value : G.expr) : extra =
(* Parser for new formula *)
(*****************************************************************************)

let formula_keys =
[ "pattern"; "all"; "any"; "regex"; "taint"; "not"; "inside" ]

let find_formula env (rule_dict : dict) : key * G.expr =
let find key_str = Hashtbl.find_opt rule_dict.h key_str in
match
find_some_opt find
[ "pattern"; "all"; "any"; "regex"; "taint"; "not"; "inside" ]
with
match find_some_opt (Hashtbl.find_opt rule_dict.h) formula_keys with
| None ->
error env.id rule_dict.first_tok
"Expected one of `pattern`, `pattern-either`, `patterns`, \
`pattern-regex` to be present"
("Expected one of " ^ String.concat "," formula_keys ^ " to be present")
| Some (key, value) -> (key, value)

(* intermediate type used for processing 'where' *)
Expand Down Expand Up @@ -1156,12 +1154,12 @@ and produce_constraint env dict tok indicator =
| Some true -> rewrite_metavar_comparison_strip cond
| _ -> cond
in
Left (t, R.CondEval cond)
[ Left (t, R.CondEval cond) ]
| Cfocus ->
(* focus: ...
*)
let mv_list = take dict env parse_focus_mvs "focus" in
Right (tok, mv_list)
[ Right (tok, mv_list) ]
| Canalyzer ->
(* metavariable: ...
analyzer: ...
Expand All @@ -1176,10 +1174,11 @@ and produce_constraint env dict tok indicator =
error_at_key env.id ("analyzer", analyze_t)
("Unsupported analyzer: " ^ other)
in
Left (t, CondAnalysis (metavar, kind))
| Cmetavar -> (
[ Left (t, CondAnalysis (metavar, kind)) ]
| Cmetavar ->
(* metavariable: ...
<pattern-pair>
[<pattern-pair>]
[type: ...]
[language: ...]
*)
let metavar, t = take dict env parse_string_wrap "metavariable" in
Expand All @@ -1197,13 +1196,32 @@ and produce_constraint env dict tok indicator =
(env', Some xlang)
| ___else___ -> (env, None)
in
let env' = { env' with in_metavariable_pattern = true } in
let formula = parse_pair env' (find_formula env dict) in
match formula with
| R.P { pat = Xpattern.Regexp regexp; _ } ->
(* TODO: always on by default *)
Left (t, CondRegexp (metavar, regexp, true))
| _ -> Left (t, CondNestedFormula (metavar, opt_xlang, formula)))
let pat =
match find_some_opt (Hashtbl.find_opt dict.h) formula_keys with
| Some ps -> (
let env' = { env' with in_metavariable_pattern = true } in
let formula = parse_pair env' ps in
match formula with
| R.P { pat = Xpattern.Regexp regexp; _ } ->
(* TODO: always on by default *)
[ Left (t, R.CondRegexp (metavar, regexp, true)) ]
| _ -> [ Left (t, CondNestedFormula (metavar, opt_xlang, formula)) ]
)
| None -> []
in
let typ =
match take_opt dict env parse_string_wrap "type" with
| Some ts ->
[
Left
( snd ts,
R.CondType
(metavar, opt_xlang, fst ts, parse_type env (metavar, t) ts)
);
]
| None -> []
in
List.flatten [ pat; typ ]

and constrain_where env (t1, _t2) where_key (value : G.expr) formula : R.formula
=
Expand All @@ -1218,6 +1236,7 @@ and constrain_where env (t1, _t2) where_key (value : G.expr) formula : R.formula
(* TODO *)
let conditions, focus =
parse_listi env where_key parse_where_pair value
|> List.flatten
|> Common.partition_either (fun x -> x)
in
let tok, conditions, focus, conjuncts =
Expand Down
6 changes: 6 additions & 0 deletions tests/rules/metavar_pattern_wrong_type_rule20.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Example {
public int foo(String a, int b) {
// ok: no-string-eqeq
if ("hello" == a) return 2;
}
}
14 changes: 14 additions & 0 deletions tests/rules/metavar_pattern_wrong_type_rule20.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
rules:
- id: no-string-eqeq
message: find errors
severity: WARNING
languages:
- java
match:
all:
- not: null == $Y
- $X == $Y
where:
- metavariable: $Y
pattern: a
type: Foo
14 changes: 14 additions & 0 deletions tests/rules/metavar_type_rule20.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
public class Example {
public int foo(String a, int b) {
// ruleid: no-string-eqeq
if (a == "hello") return 1;
// ruleid: no-string-eqeq
if ("hello" == a) return 2;
// ok: no-string-eqeq
if (b == 2) return -1;
// ok: no-string-eqeq
if (null == "hello") return 12;
// ok: no-string-eqeq
if ("hello" == null) return 0;
}
}
13 changes: 13 additions & 0 deletions tests/rules/metavar_type_rule20.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
rules:
- id: no-string-eqeq
message: find errors
severity: WARNING
languages:
- java
match:
all:
- not: null == $Y
- $X == $Y
where:
- metavariable: $Y
type: String
6 changes: 6 additions & 0 deletions tests/rules/metavar_type_wrong_pattern_rule20.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Example {
public int foo(String a, int b) {
// ok: no-string-eqeq
if ("hello" == a) return 2;
}
}
14 changes: 14 additions & 0 deletions tests/rules/metavar_type_wrong_pattern_rule20.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
rules:
- id: no-string-eqeq
message: find errors
severity: WARNING
languages:
- java
match:
all:
- not: null == $Y
- $X == $Y
where:
- metavariable: $Y
pattern: b
type: String

0 comments on commit 351e5a0

Please sign in to comment.