mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge branch 'main' into interleave-op-instr-field-flow
This commit is contained in:
22
cpp/ql/src/IDEContextual.qll
Normal file
22
cpp/ql/src/IDEContextual.qll
Normal 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("//", "/")
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
* ```
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
* ```
|
||||
|
||||
@@ -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 | |
|
||||
|
||||
Reference in New Issue
Block a user