File: null_iterator_deref.ql

package info (click to toggle)
exiv2 0.28.7%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 109,216 kB
  • sloc: cpp: 77,667; python: 9,619; javascript: 237; makefile: 193; sh: 172; ansic: 51; sed: 16
file content (47 lines) | stat: -rw-r--r-- 1,652 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * @name NULL iterator deref
 * @description Dereferencing an iterator without checking that it's valid could cause a crash.
 * @kind problem
 * @problem.severity warning
 * @id cpp/null-iterator-deref
 * @tags security
 *       external/cwe/cwe-476
 */

import cpp
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.dataflow.DataFlow

// Holds if `cond` is a condition like `use == table.end()`.
// `eq_is_true` is `true` for `==`, `false` for '!=`.
// Note: the `==` is actually an overloaded `operator==`.
predicate end_condition(GuardCondition cond, Expr use, FunctionCall endCall, boolean eq_is_true) {
  exists(FunctionCall eq |
    exists(string opName | eq.getTarget().getName() = opName |
      opName = "operator==" and eq_is_true = true
      or
      opName = "operator!=" and eq_is_true = false
    ) and
    DataFlow::localExprFlow(use, eq.getAnArgument()) and
    DataFlow::localExprFlow(endCall, eq.getAnArgument()) and
    endCall.getTarget().getName() = "end" and
    DataFlow::localExprFlow(eq, cond)
  )
}

from FunctionCall call, Expr use
where
  call.getTarget().getName() = "findKey" and
  DataFlow::localExprFlow(call, use) and
  use != call and
  not use.(AssignExpr).getRValue() = call and
  not end_condition(_, use, _, _) and
  not exists(
    Expr cond_use, FunctionCall endCall, GuardCondition cond, BasicBlock block, boolean branch
  |
    end_condition(cond, cond_use, endCall, branch) and
    DataFlow::localExprFlow(call, cond_use) and
    cond.controls(block, branch.booleanNot()) and
    block.contains(use)
  )
select call, "Iterator returned by findKey might cause a null deref $@.", use, "here"