Publishing queries to the OSS Semmle repository

This commit is contained in:
Raul Garcia (MSFT)
2019-10-17 14:54:37 -07:00
committed by Geoffrey White
parent c66e5dd13a
commit cb8dcf7db2
81 changed files with 3422 additions and 51 deletions

View File

@@ -2,29 +2,47 @@ import cpp
class SALMacro extends Macro {
SALMacro() {
this.getFile().getBaseName() = "sal.h" or
this.getFile().getBaseName() = "specstrings_strict.h" or
this.getFile().getBaseName() = "specstrings.h"
exists(string filename | filename = this.getFile().getBaseName() |
filename = "sal.h" or
filename = "specstrings_strict.h" or
filename = "specstrings.h" or
filename = "w32p.h" or
filename = "minwindef.h"
) and
(
// Dialect for Windows 8 and above
this.getName().matches("\\_%\\_")
or
// Dialect for Windows 7
this.getName().matches("\\_\\_%")
)
}
}
pragma[noinline]
predicate isTopLevelMacroAccess(MacroAccess ma) {
not exists(ma.getParentInvocation())
}
class SALAnnotation extends MacroInvocation {
SALAnnotation() {
this.getMacro() instanceof SALMacro and
not exists(this.getParentInvocation())
isTopLevelMacroAccess(this)
}
/** Returns the `Declaration` annotated by `this`. */
Declaration getDeclaration() { annotatesAt(this, result.getADeclarationEntry(), _, _) }
Declaration getDeclaration() {
annotatesAt(this, result.getADeclarationEntry(), _, _) and
not result instanceof Type // exclude typedefs
}
/** Returns the `DeclarationEntry` annotated by `this`. */
DeclarationEntry getDeclarationEntry() { annotatesAt(this, result, _, _) }
DeclarationEntry getDeclarationEntry() {
annotatesAt(this, result, _, _) and
not result instanceof TypeDeclarationEntry // exclude typedefs
}
}
/*
* Particular SAL annotations of interest
*/
class SALCheckReturn extends SALAnnotation {
SALCheckReturn() {
exists(SALMacro m | m = this.getMacro() |
@@ -39,16 +57,16 @@ class SALNotNull extends SALAnnotation {
exists(SALMacro m | m = this.getMacro() |
not m.getName().matches("%\\_opt\\_%") and
(
m.getName().matches("\\_In%") or
m.getName().matches("\\_Out%") or
m.getName().matches("_In%") or
m.getName().matches("_Out%") or
m.getName() = "_Ret_notnull_"
)
) and
exists(Type t |
t = this.getDeclaration().(Variable).getType() or
)
and
exists(Type t
| t = this.getDeclaration().(Variable).getType() or
t = this.getDeclaration().(Function).getType()
|
t.getUnspecifiedType() instanceof PointerType
| t.getUnspecifiedType() instanceof PointerType
)
}
}
@@ -56,49 +74,139 @@ class SALNotNull extends SALAnnotation {
class SALMaybeNull extends SALAnnotation {
SALMaybeNull() {
exists(SALMacro m | m = this.getMacro() |
m.getName().matches("%\\_opt\\_%") or
m.getName().matches("\\_Ret_maybenull\\_%") or
m.getName() = "_Result_nullonfailure_"
m.getName().matches("%\\_opt\\_%") or
m.getName().matches("\\_Ret_maybenull\\_%") or
m.getName() = "_Result_nullonfailure_"
)
}
}
/*
* Implementation details
///////////////////////////////////////////////////////////////////////////////
// Implementation details
/**
* Holds if `a` annotates the declaration entry `d` and
* its start position is the `idx`th position in `file` that holds a SAL element.
*/
private predicate annotatesAt(SALAnnotation a, DeclarationEntry e, File file, int idx) {
a = salElementAt(file, idx) and
(
// Base case: `a` right before `e`
e = salElementAt(file, idx + 1)
or
// Recursive case: `a` right before some annotation on `e`
annotatesAt(_, e, file, idx + 1)
)
}
library class SALElement extends Element {
SALElement() {
this instanceof DeclarationEntry or
this instanceof SALAnnotation
}
}
/** Gets the `idx`th `SALElement` in `file`. */
private SALElement salElementAt(File file, int idx) {
interestingLoc(file, result, interestingStartPos(file, idx))
predicate annotatesAt(SALAnnotation a, DeclarationEntry d,
File file, int idx) {
annotatesAtPosition(a.(SALElement).getStartPosition(), d, file, idx)
}
/**
* Holds if an SALElement element at character `result` comes at
* position `idx` in `file`.
* Holds if `pos` is the `idx`th position in `file` that holds a SAL element,
* which annotates the declaration entry `d` (by occurring before it without
* any other declaration entries in between).
*/
private int interestingStartPos(File file, int idx) {
result = rank[idx](int otherStart | interestingLoc(file, _, otherStart))
// For performance reasons, do not mention the annotation itself here,
// but compute with positions instead. This performs better on databases
// with many annotations at the same position.
private predicate annotatesAtPosition(
SALPosition pos, DeclarationEntry d, File file, int idx
) {
pos = salRelevantPositionAt(file, idx) and
salAnnotationPos(pos) and
(
// Base case: `pos` right before `d`
d.(SALElement).getStartPosition() = salRelevantPositionAt(file, idx + 1)
or
// Recursive case: `pos` right before some annotation on `d`
annotatesAtPosition(_, d, file, idx + 1)
)
}
/** Holds if `element` in `file` is at character `startPos`. */
private predicate interestingLoc(File file, SALElement element, int startPos) {
element.getLocation().charLoc(file, startPos, _)
/**
* A parameter annotated by one or more SAL annotations.
*/
class SALParameter extends Parameter {
/** One of this parameter's annotations. */
SALAnnotation a;
SALParameter() {
annotatesAt(a, this.getADeclarationEntry(), _, _)
}
predicate isIn() { a.getMacroName().toLowerCase().matches("%\\_in%") }
predicate isOut() { a.getMacroName().toLowerCase().matches("%\\_out%") }
predicate isInOut() { a.getMacroName().toLowerCase().matches("%\\_inout%") }
}
/**
* A SAL element, i.e. a SAL annotation or a declaration entry
* that may have SAL annotations.
*/
library class SALElement extends Element {
SALElement() {
containsSALAnnotation(this.(DeclarationEntry).getFile()) or
this instanceof SALAnnotation
}
predicate hasStartPosition(File file, int line, int col) {
exists(Location loc | loc = this.getLocation() |
file = loc.getFile() and
line = loc.getStartLine() and
col = loc.getStartColumn()
)
}
predicate hasEndPosition(File file, int line, int col) {
exists(Location loc |
loc = this.(FunctionDeclarationEntry).getBlock().getLocation()
or
this = any(VariableDeclarationEntry vde |
vde.isDefinition() and
loc = vde.getVariable().getInitializer().getLocation()
)
|
file = loc.getFile() and
line = loc.getEndLine() and
col = loc.getEndColumn()
)
}
SALPosition getStartPosition() {
exists(File file, int line, int col |
this.hasStartPosition(file, line, col) and
result = MkSALPosition(file, line, col)
)
}
}
/** Holds if `file` contains a SAL annotation. */
pragma[noinline]
private predicate containsSALAnnotation(File file) {
any(SALAnnotation a).getFile() = file
}
/**
* A source-file position of a `SALElement`. Unlike location, this denotes a
* point in the file rather than a range.
*/
private newtype SALPosition =
MkSALPosition(File file, int line, int col) {
exists(SALElement e |
e.hasStartPosition(file, line, col)
or
e.hasEndPosition(file, line, col)
)
}
/** Holds if `pos` is the start position of a SAL annotation. */
pragma[noinline]
private predicate salAnnotationPos(SALPosition pos) {
any(SALAnnotation a).(SALElement).getStartPosition() = pos
}
/**
* Gets the `idx`th position in `file` that holds a SAL element,
* ordering positions lexicographically by their start line and start column.
*/
private SALPosition salRelevantPositionAt(File file, int idx) {
result = rank[idx](SALPosition pos, int line, int col |
pos = MkSALPosition(file, line, col)
|
pos
order by line, col
)
}

View File

@@ -0,0 +1,23 @@
/**
* @name SAL requires inspecting return value
* @description When a return value is discarded even though the SAL annotation
* requires inspecting it, a recoverable error may turn into a
* whole-program crash.
* @kind problem
* @problem.severity warning
* @tags reliability
* external/cwe/cwe-573
* external/cwe/cwe-252
* @opaque-id SM02344
* @microsoft.severity Important
* @id cpp/ignorereturnvaluesal
*/
import microsoft.SAL
from Function f, FunctionCall call
where call.getTarget() = f
and call instanceof ExprInVoidContext
and any(SALCheckReturn a).getDeclaration() = f
and not any(Options o).okToIgnoreReturnValue(call)
select call, "Return value of $@ discarded although a SAL annotation "+
"requires inspecting it.", f, f.getName()