sqlite3_close
API Overview
sqlite3_close is an API in sqlite3. This rule belongs to the api pair type. This rule is generated using GPTAid.
Rule Description
tip
Parameter 1 must not be used later.
info
- Tags: api pair
 - Parameter Index: 0
 - CWE Type: CWE-416
 
Rule Code
/**
 * @name UAF
 * @description description
 * @kind problem
 * @problem.severity error
 * @precision high
 * @id cpp/UAF
 * @tags security
 */
 import cpp
 import semmle.code.cpp.dataflow.TaintTracking
 import semmle.code.cpp.dataflow.DataFlow
 import semmle.code.cpp.security.Security
 import semmle.code.cpp.controlflow.Guards
 import semmle.code.cpp.valuenumbering.GlobalValueNumbering
 
Expr getMallocExpr(FunctionCall fc)
{
    exists(Expr e | 
        result = e
        and
        (
            (fc.getTarget().hasName("malloc") and e = fc)
 or (fc.getTarget().hasName("sqlite3_prepare_v2") and e = fc.getArgument(3))
 or (fc.getTarget().hasName("sqlite3_exec") and e = fc.getArgument(4))
 or (fc.getTarget().hasName("sqlite3_get_table") and e = fc.getArgument(2))
 or (fc.getTarget().hasName("sqlite3_get_table") and e = fc.getArgument(5))
 or (fc.getTarget().hasName("sqlite3_open") and e = fc.getArgument(1))
 or (fc.getTarget().hasName("sqlite3_open_v2") and e = fc.getArgument(1))
        // or
        // (fc.getTarget().hasName("new_malloc") and e = fc.getArgument(0))
        // TODO-addMallocHere
        )
    )
}
Expr getFreeExpr(FunctionCall fc)
{
        result = fc.getArgument(0)
        and
        (
            // TODO-Target-change
            fc.getTarget().hasName("sqlite3_close")
        // or
        //  fc.getTarget().hasName("new_free")
        
        )
}
 predicate isSourceFC(FunctionCall fc)
 {
//  fc.getTarget().hasName("new_malloc")
//  or 
// // TODO-addMallocFCHere
 fc.getTarget().hasName("malloc")
 or fc.getTarget().hasName("sqlite3_prepare_v2")
 or fc.getTarget().hasName("sqlite3_exec")
 or fc.getTarget().hasName("sqlite3_get_table")
 or fc.getTarget().hasName("sqlite3_get_table")
 or fc.getTarget().hasName("sqlite3_open")
 or fc.getTarget().hasName("sqlite3_open_v2")
 }
 predicate isSinkFC(FunctionCall fc)
 {
 fc.getTarget().hasName("sqlite3_close")
//  or
//  fc.getTarget().hasName("new_free")
 }
    
 DataFlow::Node getSourceNode(FunctionCall fc)
 {
     result.asExpr() = getMallocExpr(fc)
     or
     result.asDefiningArgument() = getMallocExpr(fc)
 }
 class MallocConfiguration extends DataFlow::Configuration {
    MallocConfiguration() { this = "MallocConfiguration" }
   
    override predicate isSource(DataFlow::Node source) {
        exists(FunctionCall fc | 
         isSourceFC(fc)
         and
         source = getSourceNode(fc)
          )
          or
          exists(AssignExpr ae| 
             ae.getAChild() = source.asExpr()
             or ae.getAChild() = source.asDefiningArgument()
             )
      }
     override predicate isSink(DataFlow::Node sink) {
       // sink.asExpr()
       exists(Expr e |
         sink.asExpr() = e
         or sink.asDefiningArgument() = e
       )
     }
   }
//  target is a free function
from FunctionCall target, Expr use
where
isSinkFC(target)
and exists(FunctionCall malloc | isSourceFC(malloc) and target.getAPredecessor*() = malloc)
and not target.getAnArgument() = use
and target.getASuccessor*() = use
//  and 
// isLocalVariable(getMallocExpr(target))
and  exists(Variable v| 
   v.getAnAccess() = use
   and v.getAnAccess() = getFreeExpr(target)
   and not exists(Expr malloc, MallocConfiguration cfg | 
       use.getAPredecessor*() = malloc 
   and malloc.getAPredecessor*() = target
   and
   cfg.hasFlow(DataFlow::exprNode(malloc), DataFlow::exprNode(use))
   )
       )
select target, "Freed in " + target.getLocation().toString() + ". Used in " + use.getLocation().toString()