Merge branch 'main' into interleave-op-instr-field-flow

This commit is contained in:
Mathias Vorreiter Pedersen
2020-11-10 21:15:50 +01:00
121 changed files with 2482 additions and 789 deletions

View File

@@ -0,0 +1,22 @@
/**
* Provides shared predicates related to contextual queries in the code viewer.
*/
import semmle.files.FileSystem
/**
* Returns the `File` matching the given source file name as encoded by the VS
* Code extension.
*/
cached
File getFileBySourceArchiveName(string name) {
// The name provided for a file in the source archive by the VS Code extension
// has some differences from the absolute path in the database:
// 1. colons are replaced by underscores
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
// "/C_/foo/bar"
// 3. double slashes in UNC prefixes are replaced with a single slash
// We can handle 2 and 3 together by unconditionally adding a leading slash
// before replacing double slashes.
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
}

View File

@@ -50,10 +50,12 @@ class SafeTimeGatheringFunction extends Function {
class TimeConversionFunction extends Function {
TimeConversionFunction() {
this.getQualifiedName() =
["FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
"RtlTimeToSecondsSince1970", "_mkgmtime"]
[
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
"RtlTimeToSecondsSince1970", "_mkgmtime"
]
}
}

View File

@@ -4,6 +4,7 @@
*/
import cpp
import IDEContextual
/**
* Any element that might be the source or target of a jump-to-definition
@@ -207,11 +208,3 @@ Top definitionOf(Top e, string kind) {
// later on.
strictcount(result.getLocation()) < 10
}
/**
* Returns an appropriately encoded version of a filename `name`
* passed by the VS Code extension in order to coincide with the
* output of `.getFile()` on locatable entities.
*/
cached
File getEncodedFile(string name) { result.getAbsolutePath().replaceAll(":", "_") = name }

View File

@@ -7,7 +7,6 @@ import semmle.code.cpp.dataflow.TaintTracking
import experimental.semmle.code.cpp.security.PrivateData
import semmle.code.cpp.security.FileWrite
import semmle.code.cpp.security.BufferWrite
import semmle.code.cpp.dataflow.TaintTracking
module PrivateCleartextWrite {
/**

View File

@@ -12,5 +12,5 @@ import definitions
external string selectedSourceFile();
from Top e, Top def, string kind
where def = definitionOf(e, kind) and e.getFile() = getEncodedFile(selectedSourceFile())
where def = definitionOf(e, kind) and e.getFile() = getFileBySourceArchiveName(selectedSourceFile())
select e, def, kind

View File

@@ -12,5 +12,6 @@ import definitions
external string selectedSourceFile();
from Top e, Top def, string kind
where def = definitionOf(e, kind) and def.getFile() = getEncodedFile(selectedSourceFile())
where
def = definitionOf(e, kind) and def.getFile() = getFileBySourceArchiveName(selectedSourceFile())
select e, def, kind

View File

@@ -22,6 +22,6 @@ class Cfg extends PrintASTConfiguration {
* Print All functions from the selected file.
*/
override predicate shouldPrintFunction(Function func) {
func.getFile() = getEncodedFile(selectedSourceFile())
func.getFile() = getFileBySourceArchiveName(selectedSourceFile())
}
}

View File

@@ -9,12 +9,14 @@ import cpp
class StrcatFunction extends Function {
StrcatFunction() {
getName() =
["strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l"] // _mbsncat_l(dst, src, max_amount, locale)
[
"strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
]
}
}

View File

@@ -677,6 +677,11 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel |
f.hasDataFlow(inModel, outModel) and
(
exists(int iIn |
inModel.isParameterDeref(iIn) and
call.passesByReference(iIn, fromExpr)
)
or
exists(int iIn |
inModel.isParameter(iIn) and
fromExpr = call.getArgument(iIn)

View File

@@ -441,40 +441,6 @@ class ConstructorCall extends FunctionCall {
override Constructor getTarget() { result = super.getTarget() }
}
/**
* A C++ `throw` expression.
* ```
* throw Exc(2);
* ```
*/
class ThrowExpr extends Expr, @throw_expr {
/**
* Gets the expression that will be thrown, if any. There is no result if
* `this` is a `ReThrowExpr`.
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
override string toString() { result = "throw ..." }
override int getPrecedence() { result = 1 }
}
/**
* A C++ `throw` expression with no argument (which causes the current exception to be re-thrown).
* ```
* throw;
* ```
*/
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
override string toString() { result = "re-throw exception " }
}
/**
* A call to a destructor.
* ```

View File

@@ -1146,6 +1146,40 @@ class BlockExpr extends Literal {
Function getFunction() { code_block(underlyingElement(this), unresolveElement(result)) }
}
/**
* A C++ `throw` expression.
* ```
* throw Exc(2);
* ```
*/
class ThrowExpr extends Expr, @throw_expr {
/**
* Gets the expression that will be thrown, if any. There is no result if
* `this` is a `ReThrowExpr`.
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
override string toString() { result = "throw ..." }
override int getPrecedence() { result = 1 }
}
/**
* A C++ `throw` expression with no argument (which causes the current exception to be re-thrown).
* ```
* throw;
* ```
*/
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
override string toString() { result = "re-throw exception " }
}
/**
* A C++11 `noexcept` expression, returning `true` if its subexpression is guaranteed
* not to `throw` exceptions. For example:

View File

@@ -243,8 +243,10 @@ pragma[noinline]
private predicate getWrittenField(Instruction instr, Field f, Class c) {
exists(FieldAddressInstruction fa |
fa =
getFieldInstruction([instr.(StoreInstruction).getDestinationAddress(),
instr.(WriteSideEffectInstruction).getDestinationAddress()]) and
getFieldInstruction([
instr.(StoreInstruction).getDestinationAddress(),
instr.(WriteSideEffectInstruction).getDestinationAddress()
]) and
f = fa.getField() and
c = f.getDeclaringType()
)

View File

@@ -1577,6 +1577,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument operand at the specified index.
*/
pragma[noinline]
final PositionalArgumentOperand getPositionalArgumentOperand(int index) {
result = getAnOperand() and
result.getIndex() = index
@@ -1585,6 +1586,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument at the specified index.
*/
pragma[noinline]
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}

View File

@@ -1577,6 +1577,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument operand at the specified index.
*/
pragma[noinline]
final PositionalArgumentOperand getPositionalArgumentOperand(int index) {
result = getAnOperand() and
result.getIndex() = index
@@ -1585,6 +1586,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument at the specified index.
*/
pragma[noinline]
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}

View File

@@ -1577,6 +1577,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument operand at the specified index.
*/
pragma[noinline]
final PositionalArgumentOperand getPositionalArgumentOperand(int index) {
result = getAnOperand() and
result.getIndex() = index
@@ -1585,6 +1586,7 @@ class CallInstruction extends Instruction {
/**
* Gets the argument at the specified index.
*/
pragma[noinline]
final Instruction getPositionalArgument(int index) {
result = getPositionalArgumentOperand(index).getDef()
}

View File

@@ -308,8 +308,10 @@ class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
BeginOrEndFunction() {
this
.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend",
"before_begin", "cbefore_begin"]) and
.hasName([
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
"cbefore_begin"
]) and
this.getType().getUnspecifiedType() instanceof Iterator
}

View File

@@ -35,11 +35,7 @@ class ConversionConstructorModel extends Constructor, TaintFunction {
class CopyConstructorModel extends CopyConstructor, DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// data flow from the first constructor argument to the returned object
(
input.isParameter(0)
or
input.isParameterDeref(0)
) and
input.isParameterDeref(0) and
(
output.isReturnValue()
or
@@ -54,11 +50,7 @@ class CopyConstructorModel extends CopyConstructor, DataFlowFunction {
class MoveConstructorModel extends MoveConstructor, DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// data flow from the first constructor argument to the returned object
(
input.isParameter(0)
or
input.isParameterDeref(0)
) and
input.isParameterDeref(0) and
(
output.isReturnValue()
or

View File

@@ -5,9 +5,11 @@ import semmle.code.cpp.models.interfaces.SideEffect
class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction {
PureStrFunction() {
hasGlobalOrStdName(["atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr",
"strchrnul", "strstr", "strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn",
"strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"])
hasGlobalOrStdName([
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
"strtol", "strtoll", "strtoq", "strtoul"
])
}
override predicate hasArrayInput(int bufParam) {

View File

@@ -14,20 +14,24 @@ import semmle.code.cpp.models.interfaces.SideEffect
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() {
getName() =
["strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src)
"_mbscpy", // _mbscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"wcsncpy", // wcsncpy(dst, src, max_amount)
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
"_mbsncpy_l"] // _mbsncpy_l(dst, src, max_amount, locale)
[
"strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src)
"_mbscpy", // _mbscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"wcsncpy", // wcsncpy(dst, src, max_amount)
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
"_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale)
]
or
getName() =
["strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
"_mbscpy_s"] and // _mbscpy_s(dst, max_amount, src)
[
"strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
"_mbscpy_s" // _mbscpy_s(dst, max_amount, src)
] and
// exclude the 2-parameter template versions
// that find the size of a fixed size destination buffer.
getNumberOfParameters() = 3

View File

@@ -22,7 +22,7 @@ abstract class IteratorReferenceFunction extends Function { }
abstract class GetIteratorFunction extends Function {
/**
* Holds if the return value or buffer represented by `output` is an iterator over the container
* passd in the argument, qualifier, or buffer represented by `input`.
* passed in the argument, qualifier, or buffer represented by `input`.
*/
abstract predicate getsIterator(FunctionInput input, FunctionOutput output);
}

View File

@@ -355,9 +355,11 @@ class SnprintfBW extends BufferWriteCall {
class GetsBW extends BufferWriteCall {
GetsBW() {
getTarget().(TopLevelFunction).getName() =
["gets", // gets(dst)
"fgets", // fgets(dst, max_amount, src_stream)
"fgetws"] // fgetws(dst, max_amount, src_stream)
[
"gets", // gets(dst)
"fgets", // fgets(dst, max_amount, src_stream)
"fgetws" // fgetws(dst, max_amount, src_stream)
]
}
/**

View File

@@ -678,7 +678,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
override string getAPrimaryQlClass() { result = "CoReturnStmt" }
/**
* Gets the operand of this 'co_return' statement.
* Gets the operand of this `co_return` statement.
*
* For example, for
* ```
@@ -693,7 +693,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
FunctionCall getOperand() { result = this.getChild(0) }
/**
* Gets the expression of this 'co_return' statement, if any.
* Gets the expression of this `co_return` statement, if any.
*
* For example, for
* ```
@@ -707,7 +707,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
Expr getExpr() { result = this.getOperand().getArgument(0) }
/**
* Holds if this 'co_return' statement has an expression.
* Holds if this `co_return` statement has an expression.
*
* For example, this holds for
* ```

View File

@@ -5113,10 +5113,11 @@
| swap1.cpp:109:5:109:30 | ... = ... | swap1.cpp:111:20:111:24 | data1 | |
| swap1.cpp:109:5:109:30 | ... = ... | swap1.cpp:115:18:115:22 | data1 | |
| swap1.cpp:109:23:109:28 | call to source | swap1.cpp:109:5:109:30 | ... = ... | |
| swap1.cpp:113:31:113:39 | call to move | swap1.cpp:113:31:113:51 | call to Class | |
| swap1.cpp:113:31:113:39 | call to move | swap1.cpp:113:31:113:51 | call to Class | TAINT |
| swap1.cpp:113:31:113:39 | ref arg call to move | swap1.cpp:113:41:113:49 | move_from [inner post update] | |
| swap1.cpp:113:31:113:51 | call to Class | swap1.cpp:115:10:115:16 | move_to | |
| swap1.cpp:113:41:113:49 | move_from | swap1.cpp:113:31:113:39 | call to move | |
| swap1.cpp:113:41:113:49 | move_from | swap1.cpp:113:31:113:51 | call to Class | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:122:5:122:5 | x | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:124:10:124:10 | x | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:127:19:127:19 | x | |
@@ -5279,10 +5280,11 @@
| swap2.cpp:109:5:109:30 | ... = ... | swap2.cpp:111:20:111:24 | data1 | |
| swap2.cpp:109:5:109:30 | ... = ... | swap2.cpp:115:18:115:22 | data1 | |
| swap2.cpp:109:23:109:28 | call to source | swap2.cpp:109:5:109:30 | ... = ... | |
| swap2.cpp:113:31:113:39 | call to move | swap2.cpp:113:31:113:51 | call to Class | |
| swap2.cpp:113:31:113:39 | call to move | swap2.cpp:113:31:113:51 | call to Class | TAINT |
| swap2.cpp:113:31:113:39 | ref arg call to move | swap2.cpp:113:41:113:49 | move_from [inner post update] | |
| swap2.cpp:113:31:113:51 | call to Class | swap2.cpp:115:10:115:16 | move_to | |
| swap2.cpp:113:41:113:49 | move_from | swap2.cpp:113:31:113:39 | call to move | |
| swap2.cpp:113:41:113:49 | move_from | swap2.cpp:113:31:113:51 | call to Class | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:122:5:122:5 | x | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:124:10:124:10 | x | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:127:19:127:19 | x | |