xref: /freebsd/sys/contrib/openzfs/.github/codeql/custom-queries/cpp/dslDatasetHoldReleMismatch.ql (revision 4b15965daa99044daf184221b7c283bf7f2d7e66)
1/**
2 * @name Detect mismatched dsl_dataset_hold/_rele pairs
3 * @description Flags instances of issue #12014 where
4 *   - a dataset held with dsl_dataset_hold_obj() ends up in dsl_dataset_rele_flags(), or
5 *   - a dataset held with dsl_dataset_hold_obj_flags() ends up in dsl_dataset_rele().
6 * @kind problem
7 * @severity error
8 * @tags correctness
9 * @id cpp/dslDatasetHoldReleMismatch
10 */
11
12import cpp
13
14from Variable ds, Call holdCall, Call releCall, string message
15where
16    ds.getType().toString() = "dsl_dataset_t *" and
17    holdCall.getASuccessor*() = releCall and
18    (
19        (holdCall.getTarget().getName() = "dsl_dataset_hold_obj_flags" and
20         holdCall.getArgument(4).(AddressOfExpr).getOperand().(VariableAccess).getTarget() = ds and
21         releCall.getTarget().getName() = "dsl_dataset_rele" and
22         releCall.getArgument(0).(VariableAccess).getTarget() = ds and
23         message = "Held with dsl_dataset_hold_obj_flags but released with dsl_dataset_rele")
24        or
25        (holdCall.getTarget().getName() = "dsl_dataset_hold_obj" and
26         holdCall.getArgument(3).(AddressOfExpr).getOperand().(VariableAccess).getTarget() = ds and
27         releCall.getTarget().getName() = "dsl_dataset_rele_flags" and
28         releCall.getArgument(0).(VariableAccess).getTarget() = ds and
29         message = "Held with dsl_dataset_hold_obj but released with dsl_dataset_rele_flags")
30    )
31select releCall,
32       "Mismatched release: held with $@ but released with " + releCall.getTarget().getName() + " for dataset $@",
33       holdCall, holdCall.getTarget().getName(),
34       ds, ds.toString()
35