mirror of
https://github.com/hohn/codeql-workshop-dataflow-c.git
synced 2025-12-15 18:23:04 +01:00
Initial commit
This commit is contained in:
12
.gitignore
vendored
Normal file
12
.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
.cache
|
||||
*.testproj
|
||||
*.lock.yaml
|
||||
*.lock.yml
|
||||
*.actual
|
||||
exercises-tests/*/test.c
|
||||
solutions-tests/*/test.c
|
||||
cpp-dataflow-part1-database
|
||||
cpp-dataflow-part2-database
|
||||
cpp-dataflow-part3-database
|
||||
settings.json
|
||||
.DS_Store
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
370
README.md
Normal file
370
README.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# CodeQL Workshop — Applied Data-Flow and Control-Flow Analysis for C and C++
|
||||
|
||||
## Introduction
|
||||
In this workshop, we will use a CodeQL to analyse a synthetic example program that receives an `input` array parameter and an `input_types` parameter describing the *expected* type of each element of `input`. The goal of the exercise is to use data-flow, control-flow, and runtime value analysis to identify uses of `input` that are not validated against `input_types`.
|
||||
|
||||
This workshop consists of the following three parts, which can be followed in sequence or individually:
|
||||
1. Basic control-flow and data-flow analysis using local and global data-flow to identify flow from input parameters to unvalidated use. (Beginner)
|
||||
2. Identifying mismatched type validation, debugging data-flow by using partial flow analysis, and adding missing flow steps. (Intermediate)
|
||||
3. Further improving the query by using flow-state and runtime value analysis. (Advanced, WIP)
|
||||
|
||||
Understanding basic syntactic program analysis and control-flow analysis is a prerequisite to this workshop. If you are not familiar with these concepts, we recommend that you complete [CodeQL Workshop: Syntactical Elements of C/C++](https://github.com/rvermeulen/codeql-workshop-elements-of-syntactical-program-analysis-cpp) and [CodeQL Workshop for C/C++: Control Flow](https://github.com/rvermeulen/codeql-workshop-control-flow-cpp) first. We recommend that you are familiar with the CodeQL language, the CodeQL standard libraries, and data-flow analysis at an elementary level.
|
||||
|
||||
As you work through each exercise in this workshop, validate your exercise query by running the associated `exercises-tests` test (under the `Testing` section in the VS Code sidebar).
|
||||
|
||||
You can view an example solution for each exercise in the `solutions` directory.
|
||||
|
||||
## Setup instructions
|
||||
- Install [Visual Studio Code](https://code.visualstudio.com/).
|
||||
- Install the [CodeQL extension for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/setting-up-codeql-in-visual-studio-code/).
|
||||
- Install the latest version of the [CodeQL CLI](https://github.com/github/codeql-cli-binaries/releases).
|
||||
- Clone this repository:
|
||||
```bash
|
||||
git clone https://github.com/kraiouchkine/codeql-workshop-dataflow-cpp.git
|
||||
```
|
||||
- Install the CodeQL pack dependencies using the command `CodeQL: Install Pack Dependencies` and select `exercises`, `solutions`, `exercises-tests`, and `solutions-tests` from the list of packs.
|
||||
- Build the databases using `build-databases.sh` and load the appropriate database for each part of the workshop with the VS Code CodeQL extension. Alternatively, you can download the following prebuilt databases:
|
||||
- [Pre-built CodeQL Database for Part 1]()
|
||||
- [Pre-built CodeQL Database for Part 2]()
|
||||
- [Pre-built CodeQL Database for Part 3]()
|
||||
- :exclamation:Important:exclamation:: Run `initialize-qltests.sh` to initialize the tests. Otherwise, you will not be able to run the QLTests (in `exercises-tests` and `solutions-tests`).
|
||||
|
||||
## Example Problem
|
||||
To illustrate this problem, consider the following simplified example:
|
||||
```c
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DYN_INPUT_TYPE_NONE 0x0
|
||||
#define DYN_INPUT_TYPE_MEM 0x1
|
||||
#define DYN_INPUT_TYPE_VAL 0x2
|
||||
|
||||
unsigned int DYN_INPUT_TYPE(unsigned int p0, unsigned int p1) {
|
||||
return ((p0) | ((p1) << 4));
|
||||
}
|
||||
|
||||
typedef union dyn_input {
|
||||
int val;
|
||||
struct {
|
||||
void *buf;
|
||||
size_t size;
|
||||
} ptr;
|
||||
} dyn_input_t;
|
||||
|
||||
void EP_example(dyn_input_t input[2], unsigned int input_types, unsigned int unused) {
|
||||
if (input_types = DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_VAL)) {
|
||||
// input[0].ptr.buf is a pointer to a buffer
|
||||
// input[0].ptr.size is the size of the buffer
|
||||
void *buf = malloc(input[0].ptr.size);
|
||||
memcpy(buf, input[0].ptr.buf, input[0].ptr.size); // COMPLIANT
|
||||
// ...
|
||||
int val = input[0].val; // NON_COMPLIANT - wrong type
|
||||
val = input[1].val; // COMPLIANT
|
||||
}
|
||||
if (input_types = DYN_INPUT_TYPE(DYN_INPUT_TYPE_NONE, DYN_INPUT_TYPE_VAL)) {
|
||||
int val = input[0].val; // NON_COMPLIANT - wrong type
|
||||
val = input[1].val; // COMPLIANT
|
||||
}
|
||||
input[0].ptr; // NON_COMPLIANT - wrong type
|
||||
input[2].ptr; // NON_COMPLIANT - out-of-bounds, wrong type
|
||||
}
|
||||
```
|
||||
|
||||
The `EP_example` function in this example has three parameters: `input`, `input_types`, and `unused`. `input` is an array of `dyn_input_t` structures, and `input_types` is a `dyn_param_types_t` value, defining the expected types of each element in `input`. The `dyn_input_t` structure is a union of an integer `val` field and a `ptr` field. The `ptr` field is a structure containing a `buf` pointer and a `size` value.
|
||||
|
||||
An `input_types` value describes the type of each element of a `dyn_input_t` array. The `DYN_INPUT_TYPE` macro is used to pack a value from two `DYN_INPUT_TYPE_*` constants (one for each element of the input array). These constants define three possible access rules:
|
||||
- `DYN_INPUT_TYPE_NONE`: The input is not used and must not be accessed
|
||||
- `DYN_INPUT_TYPE_MEM`: The input can only be accessed via the `ptr` field
|
||||
- `DYN_INPUT_TYPE_VAL`: The input can only be accessed via the `val` field
|
||||
|
||||
Before use, `input_types` must be validated against an expected value. If no such validation exists, or if the subsequent use does not match the validation, the use may result in undefined behaviour.
|
||||
|
||||
## Part 1: Introduction to Data-Flow Analysis by Modeling Missing Type Validation
|
||||
### Exercise 1
|
||||
Output all expressions that access a `dynamic_input_t` array. Accessing dynamic inputs involves an `ArrayExpr` where the base type of the array type accessed is `dynamic_input_t`. These expressions can be thought of as "sinks" for the purpose of data-flow analysis.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
- Use `.getArrayBase().getType().(DerivedType).getBaseType().getName()`
|
||||
|
||||
</details>
|
||||
|
||||
### Exercise 2
|
||||
Next, we want to find some cases of dynamic input accesses that are guarded by type validation. Usage of dynamic input is considered unsafe if its type is not validated.
|
||||
|
||||
Here are two examples of how validation checks might be implemented:
|
||||
```c
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_VAL)) {
|
||||
// access
|
||||
}
|
||||
```
|
||||
```c
|
||||
unsigned int expected_types = DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_VAL);
|
||||
if(expected_types != input_types) {
|
||||
return;
|
||||
}
|
||||
// access
|
||||
```
|
||||
|
||||
Validation involves a comparison of the `input_types` parameter with a value returned from `DYN_INPUT_TYPE`, where the arguments to that call dictate the expected types of the `dynamic_input_t` array.
|
||||
|
||||
There are three steps to this exercise:
|
||||
1. Find all calls to `DYN_INPUT_TYPE`.
|
||||
2. Restrict the set of `GuardCondition`s to those that have local data-flow from the result of a `DYN_INPUT_TYPE` call.
|
||||
3. Check if the `GuardCondition` ensures equality against the result of `DYN_INPUT_TYPE` and guards the basic block of the `input` access.
|
||||
|
||||
Complete the `typeValidationGuard` predicate and output all `input` accesses that are not guarded by a type validation check.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
- Use DataFlow::localFlow(source, dest) to check if there is flow from the result of `DYN_INPUT_TYPE` to an operand of the `GuardCondition`'s `ensuresEq` check.
|
||||
- Use `getBasicBlock` to get the basic block of a `DynamicInputAccess`.
|
||||
|
||||
</details>
|
||||
|
||||
### Exercise 3
|
||||
In the previous exercise, we implemented a basic query using local data-flow and control-flow analysis. However, there are false-negatives and false-positives in cases such as the following:
|
||||
```c
|
||||
void func_nested(dyn_input_t *input, unsigned int input_types) {
|
||||
// Case 1: An access of `input` would result in a false-positive, because
|
||||
// input_types is validated in a caller of this function but not here.
|
||||
}
|
||||
void func(dyn_input_t *input, unsigned int input_types, int irrelevant_param) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_VAL)) {
|
||||
func_nested(input, input_types);
|
||||
}
|
||||
if(irrelevant_param == DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_VAL)) {
|
||||
// Case 2: An access of `input` here would result in a false-negative, because
|
||||
// irrelevant_param does not originate from an entrypoint's input_types parameter.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The solution is global data-flow analysis. Start by modeling the source, i.e. the entrypoints and their parameters. Entrypoints are functions that are not called from anywhere else in the program and match the signature `int(dynamic_input_t*, unsigned int)`.
|
||||
|
||||
Specifically, these functions are:
|
||||
- `EP_copy_mem`
|
||||
- `EP_print_val`
|
||||
- `EP_write_val_to_mem`
|
||||
|
||||
Output each entrypoint along with its `input` and `input_types` parameters.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
- Use `Function::hasName(["name1, "name2", ...])` to check if the function has a name matching an entry from a list of strings.
|
||||
- Optional: Model these entrypoints heuristically by finding functions with the above specified signature and no calls to the function.
|
||||
|
||||
</details>
|
||||
|
||||
### Exercise 4
|
||||
Model the data-flow of `input` and `input_types` from an entrypoint parameter (a source) to a use (a sink). Create two separate global data-flow configurations: one for `input` and one for `input_types` By doing so, we can:
|
||||
* Ensure that a `typeValidationGuard` validates only `input_types` and not just any value.
|
||||
* Output paths on which `input` does not have type validation before access.
|
||||
|
||||
Start by thinking about and defining the `source` and `sink` for each of the two configurations.
|
||||
|
||||
Output all paths from an entrypoint to a dynamic input access that does not have a local type validation check.
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
- The sources for `input` and `input_types` are the relevant `DataFlow::ParameterNode`s of an entrypoint.
|
||||
- The sinks for `input` are accesses of `input`.
|
||||
- The sinks for `input_types` are should be `other` in the `typeValidationGuard` predicate. However, if you try defining the sink as such, usage of that configuration in the `typeValidationGuard` predicate will result in monotonic recursion.
|
||||
|
||||
</details>
|
||||
|
||||
We have resolved the false-negatives but not the false-positives in `copy_mem_nested`, which we will resolve in the following exercise.
|
||||
|
||||
#### :exclamation: **Note** :exclamation:<br>
|
||||
In subsequent exercises, mentions of the "configuration"/"global data-flow config" refer to the `input`/access data-flow config (*not* the `input_types` to type-check configuration).
|
||||
|
||||
|
||||
### Exercise 5
|
||||
In the previous exercise, we output all paths from an entrypoint to a dynamic input access that do not have a local type validation check. However, each `copy_mem_nested` outputs three paths of which only one is a true positive.
|
||||
|
||||
The reason for these false positives lies in the `not typeValidationGuard(_, _, _, access.getBasicBlock())` condition. The `typeValidationGuard` predicate uses local data- and control-flow graphs and thus does not restrict results in functions lower in the call stack than the function performing the type checking. To resolve this false positive, restrict flow through any node in a `BasicBlock` guarded by a type check.
|
||||
|
||||
Define an `isBarrier` predicate in the data-flow configuration to block flow through `BasicBlock` already guarded by a type check.
|
||||
|
||||
The query should output all `input` accesses with missing type checks without the false-positives from previous exercises.
|
||||
|
||||
### Exercise 6
|
||||
Under construction. Skip this exercise.
|
||||
|
||||
## Part 2: Mismatched Type Validation and Debugging Data-Flow to Find Missing Flow Steps
|
||||
This part of the workshop continues from Part 1 and adds two complicating factors:
|
||||
1. Cases where type validation exists but does not match the fields subsequently accessed.
|
||||
2. Missing edges between data-flow nodes that require extra modeling.
|
||||
|
||||
Up until now, we have only associated the inputs (sources) to their access (sinks) and treated type-checking as a simple guard condition. To expand this query, we no longer want to treat type checking as only a guard condition but rather in relation to the input use.
|
||||
|
||||
It is important not to confuse control- and data-flow here.
|
||||
|
||||
We rely on the control-flow graph to:
|
||||
* Verify that the guard condition exists and to identify the subsequent blocks it guards
|
||||
|
||||
We rely on the data-flow graph to:
|
||||
* Link `DYN_INPUT_TYPE` results to guard conditions (local data-flow)
|
||||
* Link `input` parameters from entrypoints to their accesses (global data-flow)
|
||||
* Link `input_types` parameters from entrypoints to guard conditions (global data-flow)
|
||||
|
||||
Unlike the previous data-flow configuration, we need to propagate the state of the control guard conditions throughout the data-flow problem. The previous configuration simply defines data-flow nodes guarded by a specified barrier (the `input_types` guard) as guarded nodes, meaning data-flow cannot propagate through them. We now *do* want data-flow to propogate through those nodes, but we also want to note the expected type checked in the guard condition.
|
||||
|
||||
Since the first part of this workshop covers all cases with *missing* checks, we need to cover the additional cases with *mismatched* checks.
|
||||
|
||||
We can take a step back and rephrase this problem as "finding all parameter accesses without a type-check matching the type accessed."
|
||||
|
||||
### Exercise 7
|
||||
One solution to finding mismatched type checks/accesses is removing the `isBarrier` prediate and instead adding some recursive control-flow-based heuristics. To implement this solution, perform the following steps:
|
||||
1. Search for a `typeValidationGuard` guarding a dynamic input access.
|
||||
2. If no such guard exists locally, search backwards transitively from the control node at each `FunctionCall` which calls the function. In other words, perform step 1 transitively for each `FunctionCall`/callee node pair, until a guard condition is found.
|
||||
|
||||
Output all dynamic input accesses and each `GuardCondition` that guards it or a guarded `FunctionCall` that calls the function containing the access.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
* Define a new predicate: `typeValidationGuardOrIndirect`
|
||||
* `typeValidationGuardOrIndirect` should check if exists a `typeValidationGuard` for `block` or `block.getEnclosingFunction().getACallToThisFunction().getBasicBlock()`.
|
||||
* Relate each input access to a `controllingGuardConditionOrIndirect`.
|
||||
|
||||
</details>
|
||||
|
||||
Before moving to the next exercise, try to answer the following question:
|
||||
"Why might this solution produce more inaccurate results than the previous solution with an `isBarrier` predicate?"
|
||||
|
||||
<details>
|
||||
<summary>Answer</summary>
|
||||
|
||||
* Unlike global data-flow analysis, which is path sensitive, our control-flow analysis is path-insensitive and does not preserve state in certain cases.
|
||||
* What if the guard condition occurs in a function that calls another function twice in two branches, with one branch correctly validating the type and the other not?
|
||||
* Without outputting each (access, guard) pair instead of a path graph, there is no path-sensitive output.
|
||||
* Part 3 of this workshop explores a solution to this problem using flow-state.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### Exercise 8
|
||||
To detect mismatched type validation, extract the type specified for each input in a call to `DYN_INPUT_TYPE` and compare it to the type of access.
|
||||
|
||||
| Input Type | Description |
|
||||
|---------------------|-------------------------------------------------------------------|
|
||||
| DYN_INPUT_TYPE_NONE | The input at this index does not exist and may not be accessed. |
|
||||
| DYN_INPUT_TYPE_MEM | The input at this index may only be accessed via its `ptr` field. |
|
||||
| DYN_INPUT_TYPE_VAL | The input at this index may only be accessed via its `val` field. |
|
||||
|
||||
Output every access that has a missing type check or a type-check that does not match the type of access.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
* Find a `FieldAccess fa` where `fa.getQualifier()` is an `ArrayExpr` and `fa.getTarget().getName()` is the name of the field accessed.
|
||||
* Use `.getValue().getInt()` to get the integer value of a `DYN_INPUT_TYPE` argument.
|
||||
|
||||
</details>
|
||||
|
||||
### Exercise 9
|
||||
Combine the logic from the previous exercise back into the data-flow configuration so that we have some path-sensitivity and can output specific paths from entry-points to dynamic input accesses that do not have a type check matching the type accessed. You should now see multiple results with flow paths when running the query.
|
||||
|
||||
Compare the results from Exercise 8 and Exercise 9; what are the differences, and what might be causing those differences?
|
||||
|
||||
<details>
|
||||
<summary>Answer</summary>
|
||||
|
||||
* This exercise is missing some results in `copy_mem`.
|
||||
* The reason for the false-negatives stems from this exercise restricting the set of dynamic input accesses to those that flow from an entrypoint parameter source. The missing results mean that there are paths from entrypoint parameter sources to dynamic input access sinks that are missing edges between two data-flow nodes.
|
||||
* Furthermore, this query does not exclude safe paths, if multiple paths exist, to a `DynamicInputAccess` that only has *some* paths that are unsafe.
|
||||
|
||||
</details>
|
||||
|
||||
### Optional: Exercise 10
|
||||
This exercise does not improve the query's output but is a good example of the limitations of not using flow-state. To try to exclude safe interprocedural paths from the results, define function call arguments guarded by compliant type checks as barriers with the `isBarrier` predicate.
|
||||
|
||||
Think of this exercise as the opposite of the `isTypeNotValidated` predicate implemented in the previous exercises; we want to find a valid type validation guard and block flow through its basic block.
|
||||
|
||||
Implement the `isTypeValidationGuardCompliant` predicate and use it as part of the solution in `isBarrier` along with `typeValidationGuard`.
|
||||
|
||||
What is the problem with this implementation?
|
||||
|
||||
<details>
|
||||
<summary>Answer</summary>
|
||||
|
||||
* This implementation will block flow through any basic block that contains a valid type validation guard for *any* `DynamicInputAccess` – not just the eventual sink. This means that if there are multiple paths to varying `DynamicInputAccess` sinks, the query will not output any results for that any sinks along that path even if the validation is mismatched.
|
||||
|
||||
</details>
|
||||
|
||||
## Exercise 11
|
||||
Continuing from Exercise 9 (Exercise 10 is optional), there are still missing results. To identify the missing edges, we can debug our data-flow configuration. The CodeQL standard library provides the `Impl::FlowExploration` module, which exposes the `hasPartialFlow` predicate, allowing you to view partial flow paths. The `Impl::FlowExploration::PartialPathGraph` module must be imported to view the results of `hasPartialFlow` as paths.
|
||||
|
||||
This exercise only requires you to understand the query and evaluate its results; `Exercise10.ql` is otherwise complete. The query serves as a demonstration for using partial flow.
|
||||
|
||||
What is the missing edge?
|
||||
|
||||
<details>
|
||||
<summary>Answer</summary>
|
||||
|
||||
* The missing edge is between the `input` parameter and return value of calls to `lock_input`.
|
||||
|
||||
</details>
|
||||
|
||||
## Exercise 12
|
||||
In this final exercise for Part 2, in the global data-flow configuration, add an additional flow step between the `input` parameter and the `output` parameter of calls to `lock_input` to add the missing edges.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
* Use `Node::asDefiningArgument` to model the `output` parameter.
|
||||
* Use `Node::asExpr` to model the `input` parameter.
|
||||
|
||||
</details>
|
||||
|
||||
You should now see additional results through flow paths that include `lock_input`.
|
||||
|
||||
Optional: Re-add the barrier checks from `Exercise10` to see their impact on a larger set of results.
|
||||
|
||||
# End of workshop
|
||||
|
||||
This workshop is currently in ongoing development. Planned topics include:
|
||||
- Outputting flow state context for each result (currently, state is only bound inside the data-flow configuration).
|
||||
- Using runtime value analysis to identify type checks with patterns differing from `DYN_INPUT_TYPE`.
|
||||
|
||||
## Part 3: Flow-State
|
||||
The second part of this workshop built upon the data-flow and control-flow analysis from the first part to further identify cases where type validation exists but does not match the subsequent access type. However, that rudimentary recursive control-flow analysis might not work in all cases, as it does not preserve flow path state in the case of multiple function calls with varying validation states.
|
||||
|
||||
To preserve the state of type validation checks across each data-flow path, we can use flow-state.
|
||||
|
||||
### Exercise 13
|
||||
Flow states are defined by a class extending `DataFlow::FlowState`. Within a data-flow configuration, an initial flow state is specified in the `isSource` predicate and can be subsequently updated in the `isAdditionalFlowStep` and `isBarrier` predicates. The `isSink` predicate can then check the (path-sensitive) flow-state and conditionally restrict sinks based on the state on the path to the sink.
|
||||
|
||||
First define the necessary flow-state classes:
|
||||
1. Define the flow state `InputTypesNotValidated` (hint: just use FlowStateString::FlowStateEmpty).
|
||||
2. Define the flow state `InputTypesValidated` with a [field declaration](https://codeql.github.com/docs/ql-language-reference/types/#fields) specifying the type validation call. Implement a `getValidatedType()` predicate to return the field.
|
||||
|
||||
Note the changes in the data-flow configuration in Exercise13.ql: some predicates now have one or more `state` parameters. Complete the predicates to implement the flow-state logic.
|
||||
|
||||
For now, in `isSink`, only check if the state is `InputTypesNotValidated`.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
* `isSource` should check if state is an `instanceof` `InputTypesNotValidated`.
|
||||
* In `isAdditionalFlowStep`, we don't actually want to add another additional flow step. However, we should restrict the new state to be an `instanceof InputTypesValidated`, where `InputTypesValidated::getValidatedType()` is derived from
|
||||
the call column of `typeValidationGuard`.
|
||||
|
||||
</details>
|
||||
|
||||
Output all flow paths. You should see all results that do not have type validation.
|
||||
|
||||
### Exercise 14
|
||||
In this final exercise, complete the `isSink` predicate to include cases where the state is `InputTypesValidated` and the expected type *does not* match the access type.
|
||||
|
||||
You should now see path-sensitive results with no false-negatives or false-positives.
|
||||
|
||||
<details>
|
||||
<summary>Hint</summary>
|
||||
|
||||
* Use `typeValidationCallMatchesUse` in `isSink`.
|
||||
|
||||
</details>
|
||||
16
build-databases.sh
Executable file
16
build-databases.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
[[ $(git rev-parse --show-toplevel) == $(pwd) ]] || {
|
||||
echo "This script must be run from the root of the workshop repository."
|
||||
exit 1
|
||||
}
|
||||
|
||||
for i in {1..3}; do
|
||||
SRCDIR=$(pwd)/tests-common
|
||||
DB=$(pwd)/cpp-dataflow-part$i-database
|
||||
|
||||
echo $DB
|
||||
test -d "$DB" && rm -fR "$DB"
|
||||
mkdir -p "$DB"
|
||||
|
||||
codeql database create --language=cpp -s "$SRCDIR" -j 8 -v $DB --command="clang -fsyntax-only $SRCDIR/test_part$i.c"
|
||||
done
|
||||
2
codeql-workspace.yml
Normal file
2
codeql-workspace.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
provides:
|
||||
- "*/*.qlpack"
|
||||
25
exercises-tests/Exercise1/Exercise1.expected
Normal file
25
exercises-tests/Exercise1/Exercise1.expected
Normal file
@@ -0,0 +1,25 @@
|
||||
| test.c:30:10:30:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:30:28:30:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:31:10:31:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:36:10:36:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:36:28:36:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:37:10:37:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:43:10:43:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:43:28:43:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:44:10:44:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:48:12:48:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:48:30:48:37 | access to array | Access of dynamic input array. |
|
||||
| test.c:49:12:49:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:56:10:56:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:56:28:56:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:57:10:57:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:65:18:65:25 | access to array | Access of dynamic input array. |
|
||||
| test.c:66:18:66:25 | access to array | Access of dynamic input array. |
|
||||
| test.c:70:16:70:23 | access to array | Access of dynamic input array. |
|
||||
| test.c:71:16:71:23 | access to array | Access of dynamic input array. |
|
||||
| test.c:77:12:77:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:77:31:77:38 | access to array | Access of dynamic input array. |
|
||||
| test.c:78:19:78:26 | access to array | Access of dynamic input array. |
|
||||
| test.c:82:10:82:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:82:29:82:36 | access to array | Access of dynamic input array. |
|
||||
| test.c:83:17:83:24 | access to array | Access of dynamic input array. |
|
||||
1
exercises-tests/Exercise1/Exercise1.qlref
Normal file
1
exercises-tests/Exercise1/Exercise1.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise1.ql
|
||||
59
exercises-tests/Exercise10/Exercise10.expected
Normal file
59
exercises-tests/Exercise10/Exercise10.expected
Normal file
@@ -0,0 +1,59 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
exercises-tests/Exercise10/Exercise10.qlref
Normal file
1
exercises-tests/Exercise10/Exercise10.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise10.ql
|
||||
156
exercises-tests/Exercise11/Exercise11.expected
Normal file
156
exercises-tests/Exercise11/Exercise11.expected
Normal file
@@ -0,0 +1,156 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:31:35:31:39 | input indirection |
|
||||
| test.c:31:35:31:39 | input | test.c:31:35:31:39 | input indirection |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:31:35:31:39 | input |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:33:10:33:14 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:33:10:33:14 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:36:48:36:52 | input indirection |
|
||||
| test.c:36:48:36:52 | input | test.c:36:48:36:52 | input indirection |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:36:48:36:52 | input |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:45:22:45:26 | input |
|
||||
| test.c:45:3:45:27 | ... = ... | test.c:46:10:46:14 | input |
|
||||
| test.c:45:11:45:20 | call to lock_input | test.c:45:3:45:27 | ... = ... |
|
||||
| test.c:45:22:45:26 | input | test.c:45:22:45:26 | input |
|
||||
| test.c:46:10:46:14 | input | test.c:46:10:46:14 | input |
|
||||
| test.c:46:10:46:14 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:46:28:46:32 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:46:28:46:32 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:47:10:47:14 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:47:10:47:14 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:51:12:51:16 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:51:12:51:16 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:51:30:51:34 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:51:30:51:34 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:52:12:52:16 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:52:12:52:16 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:55:21:55:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:58:7:58:17 | Phi | test.c:63:10:63:14 | input |
|
||||
| test.c:63:10:63:14 | input | test.c:63:10:63:14 | input |
|
||||
| test.c:63:10:63:14 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:64:10:64:14 | input |
|
||||
| test.c:64:10:64:14 | input | test.c:64:10:64:14 | input |
|
||||
| test.c:64:10:64:14 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:70:28:70:32 | input indirection |
|
||||
| test.c:70:28:70:32 | input | test.c:70:28:70:32 | input indirection |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:70:28:70:32 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:72:18:72:22 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:72:18:72:22 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:79:16:79:20 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:72:18:72:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:72:18:72:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:80:16:80:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:80:16:80:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:84:35:84:39 | input indirection |
|
||||
| test.c:84:35:84:39 | input | test.c:84:35:84:39 | input indirection |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:84:35:84:39 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:86:12:86:16 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:86:12:86:16 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:93:10:93:14 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:12:86:16 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:12:86:16 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:89:26:89:30 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:89:26:89:30 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:104:29:104:33 | input indirection |
|
||||
| test.c:104:29:104:33 | input | test.c:104:29:104:33 | input indirection |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:104:29:104:33 | input |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:105:22:105:26 | input |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:108:30:108:34 | input indirection |
|
||||
| test.c:108:30:108:34 | input | test.c:108:30:108:34 | input indirection |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:108:30:108:34 | input |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:109:20:109:24 | input |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:112:37:112:41 | input indirection |
|
||||
| test.c:112:37:112:41 | input | test.c:112:37:112:41 | input indirection |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:112:37:112:41 | input |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:113:27:113:31 | input |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:113:27:113:31 | input |
|
||||
#select
|
||||
| test.c:31:35:31:39 | input | test.c:104:29:104:33 | input | test.c:31:35:31:39 | input | Partial flow |
|
||||
| test.c:31:35:31:39 | input | test.c:108:30:108:34 | input | test.c:31:35:31:39 | input | Partial flow |
|
||||
| test.c:36:48:36:52 | input | test.c:104:29:104:33 | input | test.c:36:48:36:52 | input | Partial flow |
|
||||
| test.c:45:22:45:26 | input | test.c:104:29:104:33 | input | test.c:45:22:45:26 | input | Partial flow |
|
||||
| test.c:70:28:70:32 | input | test.c:108:30:108:34 | input | test.c:70:28:70:32 | input | Partial flow |
|
||||
| test.c:84:35:84:39 | input | test.c:112:37:112:41 | input | test.c:84:35:84:39 | input | Partial flow |
|
||||
1
exercises-tests/Exercise11/Exercise11.qlref
Normal file
1
exercises-tests/Exercise11/Exercise11.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise11.ql
|
||||
92
exercises-tests/Exercise12/Exercise12.expected
Normal file
92
exercises-tests/Exercise12/Exercise12.expected
Normal file
@@ -0,0 +1,92 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:46:10:46:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:46:10:46:14 | input | semmle.label | input |
|
||||
| test.c:46:28:46:32 | input | semmle.label | input |
|
||||
| test.c:47:10:47:14 | input | semmle.label | input |
|
||||
| test.c:48:19:48:23 | input | semmle.label | input |
|
||||
| test.c:51:12:51:16 | input | semmle.label | input |
|
||||
| test.c:51:30:51:34 | input | semmle.label | input |
|
||||
| test.c:52:12:52:16 | input | semmle.label | input |
|
||||
| test.c:55:21:55:25 | input | semmle.label | input |
|
||||
| test.c:65:19:65:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:75:21:75:25 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:10:32:14 | input | test.c:108:30:108:34 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:108:30:108:34 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:108:30:108:34 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:46:10:46:14 | input | test.c:104:29:104:33 | input | test.c:46:10:46:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:46:28:46:32 | input | test.c:104:29:104:33 | input | test.c:46:28:46:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:47:10:47:14 | input | test.c:104:29:104:33 | input | test.c:47:10:47:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:51:12:51:16 | input | test.c:104:29:104:33 | input | test.c:51:12:51:16 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:51:30:51:34 | input | test.c:104:29:104:33 | input | test.c:51:30:51:34 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:52:12:52:16 | input | test.c:104:29:104:33 | input | test.c:52:12:52:16 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
exercises-tests/Exercise12/Exercise12.qlref
Normal file
1
exercises-tests/Exercise12/Exercise12.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise12.ql
|
||||
14
exercises-tests/Exercise2/Exercise2.expected
Normal file
14
exercises-tests/Exercise2/Exercise2.expected
Normal file
@@ -0,0 +1,14 @@
|
||||
| test.c:30:10:30:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:23 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:23 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:36 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:83:17:83:24 | access to array | Access to dynamic input array without type validation. |
|
||||
1
exercises-tests/Exercise2/Exercise2.qlref
Normal file
1
exercises-tests/Exercise2/Exercise2.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise2.ql
|
||||
3
exercises-tests/Exercise3/Exercise3.expected
Normal file
3
exercises-tests/Exercise3/Exercise3.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
| test.c:93:5:93:15 | EP_copy_mem | test.c:93:29:93:33 | input | test.c:93:52:93:62 | input_types |
|
||||
| test.c:97:5:97:16 | EP_print_val | test.c:97:30:97:34 | input | test.c:97:53:97:63 | input_types |
|
||||
| test.c:101:5:101:23 | EP_write_val_to_mem | test.c:101:37:101:41 | input | test.c:101:60:101:70 | input_types |
|
||||
1
exercises-tests/Exercise3/Exercise3.qlref
Normal file
1
exercises-tests/Exercise3/Exercise3.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise3.ql
|
||||
77
exercises-tests/Exercise4/Exercise4.expected
Normal file
77
exercises-tests/Exercise4/Exercise4.expected
Normal file
@@ -0,0 +1,77 @@
|
||||
edges
|
||||
| test.c:29:35:29:39 | input | test.c:30:10:30:14 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:30:28:30:32 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:31:10:31:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:10:36:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:28:36:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:37:10:37:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:38:19:38:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:10:43:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:28:43:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:44:10:44:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:45:19:45:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:12:48:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:30:48:34 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:49:12:49:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:58:19:58:23 | input |
|
||||
| test.c:38:19:38:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:45:19:45:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:58:19:58:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:70:16:70:20 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:71:16:71:20 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:10:82:14 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:29:82:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:94:22:94:26 | input |
|
||||
| test.c:94:22:94:26 | input | test.c:34:48:34:52 | input |
|
||||
| test.c:97:30:97:34 | input | test.c:98:20:98:24 | input |
|
||||
| test.c:98:20:98:24 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:101:37:101:41 | input | test.c:102:27:102:31 | input |
|
||||
| test.c:102:27:102:31 | input | test.c:75:35:75:39 | input |
|
||||
nodes
|
||||
| test.c:29:35:29:39 | input | semmle.label | input |
|
||||
| test.c:30:10:30:14 | input | semmle.label | input |
|
||||
| test.c:30:28:30:32 | input | semmle.label | input |
|
||||
| test.c:31:10:31:14 | input | semmle.label | input |
|
||||
| test.c:34:48:34:52 | input | semmle.label | input |
|
||||
| test.c:36:10:36:14 | input | semmle.label | input |
|
||||
| test.c:36:28:36:32 | input | semmle.label | input |
|
||||
| test.c:37:10:37:14 | input | semmle.label | input |
|
||||
| test.c:38:19:38:23 | input | semmle.label | input |
|
||||
| test.c:43:10:43:14 | input | semmle.label | input |
|
||||
| test.c:43:28:43:32 | input | semmle.label | input |
|
||||
| test.c:44:10:44:14 | input | semmle.label | input |
|
||||
| test.c:45:19:45:23 | input | semmle.label | input |
|
||||
| test.c:48:12:48:16 | input | semmle.label | input |
|
||||
| test.c:48:30:48:34 | input | semmle.label | input |
|
||||
| test.c:49:12:49:16 | input | semmle.label | input |
|
||||
| test.c:58:19:58:23 | input | semmle.label | input |
|
||||
| test.c:63:28:63:32 | input | semmle.label | input |
|
||||
| test.c:70:16:70:20 | input | semmle.label | input |
|
||||
| test.c:71:16:71:20 | input | semmle.label | input |
|
||||
| test.c:75:35:75:39 | input | semmle.label | input |
|
||||
| test.c:82:10:82:14 | input | semmle.label | input |
|
||||
| test.c:82:29:82:33 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:94:22:94:26 | input | semmle.label | input |
|
||||
| test.c:97:30:97:34 | input | semmle.label | input |
|
||||
| test.c:98:20:98:24 | input | semmle.label | input |
|
||||
| test.c:101:37:101:41 | input | semmle.label | input |
|
||||
| test.c:102:27:102:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:30:10:30:14 | input | test.c:93:29:93:33 | input | test.c:30:10:30:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:32 | input | test.c:93:29:93:33 | input | test.c:30:28:30:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:14 | input | test.c:93:29:93:33 | input | test.c:31:10:31:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:14 | input | test.c:93:29:93:33 | input | test.c:36:10:36:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:32 | input | test.c:93:29:93:33 | input | test.c:36:28:36:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:14 | input | test.c:93:29:93:33 | input | test.c:37:10:37:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:14 | input | test.c:93:29:93:33 | input | test.c:43:10:43:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:32 | input | test.c:93:29:93:33 | input | test.c:43:28:43:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:14 | input | test.c:93:29:93:33 | input | test.c:44:10:44:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:12:48:16 | input | test.c:93:29:93:33 | input | test.c:48:12:48:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:30:48:34 | input | test.c:93:29:93:33 | input | test.c:48:30:48:34 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:49:12:49:16 | input | test.c:93:29:93:33 | input | test.c:49:12:49:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:20 | input | test.c:97:30:97:34 | input | test.c:70:16:70:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:20 | input | test.c:97:30:97:34 | input | test.c:71:16:71:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:14 | input | test.c:101:37:101:41 | input | test.c:82:10:82:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:33 | input | test.c:101:37:101:41 | input | test.c:82:29:82:33 | input | Access to dynamic input array without type validation. |
|
||||
1
exercises-tests/Exercise4/Exercise4.qlref
Normal file
1
exercises-tests/Exercise4/Exercise4.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise4.ql
|
||||
74
exercises-tests/Exercise5/Exercise5.expected
Normal file
74
exercises-tests/Exercise5/Exercise5.expected
Normal file
@@ -0,0 +1,74 @@
|
||||
edges
|
||||
| test.c:29:35:29:39 | input | test.c:30:10:30:14 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:30:28:30:32 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:31:10:31:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:10:36:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:28:36:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:37:10:37:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:38:19:38:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:10:43:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:28:43:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:44:10:44:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:45:19:45:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:12:48:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:30:48:34 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:49:12:49:16 | input |
|
||||
| test.c:38:19:38:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:45:19:45:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:70:16:70:20 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:71:16:71:20 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:10:82:14 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:29:82:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:94:22:94:26 | input |
|
||||
| test.c:94:22:94:26 | input | test.c:34:48:34:52 | input |
|
||||
| test.c:97:30:97:34 | input | test.c:98:20:98:24 | input |
|
||||
| test.c:98:20:98:24 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:101:37:101:41 | input | test.c:102:27:102:31 | input |
|
||||
| test.c:102:27:102:31 | input | test.c:75:35:75:39 | input |
|
||||
nodes
|
||||
| test.c:29:35:29:39 | input | semmle.label | input |
|
||||
| test.c:30:10:30:14 | input | semmle.label | input |
|
||||
| test.c:30:28:30:32 | input | semmle.label | input |
|
||||
| test.c:31:10:31:14 | input | semmle.label | input |
|
||||
| test.c:34:48:34:52 | input | semmle.label | input |
|
||||
| test.c:36:10:36:14 | input | semmle.label | input |
|
||||
| test.c:36:28:36:32 | input | semmle.label | input |
|
||||
| test.c:37:10:37:14 | input | semmle.label | input |
|
||||
| test.c:38:19:38:23 | input | semmle.label | input |
|
||||
| test.c:43:10:43:14 | input | semmle.label | input |
|
||||
| test.c:43:28:43:32 | input | semmle.label | input |
|
||||
| test.c:44:10:44:14 | input | semmle.label | input |
|
||||
| test.c:45:19:45:23 | input | semmle.label | input |
|
||||
| test.c:48:12:48:16 | input | semmle.label | input |
|
||||
| test.c:48:30:48:34 | input | semmle.label | input |
|
||||
| test.c:49:12:49:16 | input | semmle.label | input |
|
||||
| test.c:63:28:63:32 | input | semmle.label | input |
|
||||
| test.c:70:16:70:20 | input | semmle.label | input |
|
||||
| test.c:71:16:71:20 | input | semmle.label | input |
|
||||
| test.c:75:35:75:39 | input | semmle.label | input |
|
||||
| test.c:82:10:82:14 | input | semmle.label | input |
|
||||
| test.c:82:29:82:33 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:94:22:94:26 | input | semmle.label | input |
|
||||
| test.c:97:30:97:34 | input | semmle.label | input |
|
||||
| test.c:98:20:98:24 | input | semmle.label | input |
|
||||
| test.c:101:37:101:41 | input | semmle.label | input |
|
||||
| test.c:102:27:102:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:30:10:30:14 | input | test.c:93:29:93:33 | input | test.c:30:10:30:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:32 | input | test.c:93:29:93:33 | input | test.c:30:28:30:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:14 | input | test.c:93:29:93:33 | input | test.c:31:10:31:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:14 | input | test.c:93:29:93:33 | input | test.c:36:10:36:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:32 | input | test.c:93:29:93:33 | input | test.c:36:28:36:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:14 | input | test.c:93:29:93:33 | input | test.c:37:10:37:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:14 | input | test.c:93:29:93:33 | input | test.c:43:10:43:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:32 | input | test.c:93:29:93:33 | input | test.c:43:28:43:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:14 | input | test.c:93:29:93:33 | input | test.c:44:10:44:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:12:48:16 | input | test.c:93:29:93:33 | input | test.c:48:12:48:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:30:48:34 | input | test.c:93:29:93:33 | input | test.c:48:30:48:34 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:49:12:49:16 | input | test.c:93:29:93:33 | input | test.c:49:12:49:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:20 | input | test.c:97:30:97:34 | input | test.c:70:16:70:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:20 | input | test.c:97:30:97:34 | input | test.c:71:16:71:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:14 | input | test.c:101:37:101:41 | input | test.c:82:10:82:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:33 | input | test.c:101:37:101:41 | input | test.c:82:29:82:33 | input | Access to dynamic input array without type validation. |
|
||||
1
exercises-tests/Exercise5/Exercise5.qlref
Normal file
1
exercises-tests/Exercise5/Exercise5.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise5.ql
|
||||
20
exercises-tests/Exercise7/Exercise7.expected
Normal file
20
exercises-tests/Exercise7/Exercise7.expected
Normal file
@@ -0,0 +1,20 @@
|
||||
WARNING: Unused method getInputParameter (/Users/kraiouchkine/internal/codeql-workshop-dataflow-c/solutions/Exercise7.ql:84,13-30)
|
||||
| test.c:32:10:32:17 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:32:10:32:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:32:10:32:17 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:63:10:63:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:63:28:63:35 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:64:10:64:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:72:18:72:25 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:73:18:73:25 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:74:19:74:26 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:86:12:86:19 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:86:31:86:38 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:87:19:87:26 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:89:26:89:33 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
1
exercises-tests/Exercise7/Exercise7.qlref
Normal file
1
exercises-tests/Exercise7/Exercise7.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise7.ql
|
||||
20
exercises-tests/Exercise8/Exercise8.expected
Normal file
20
exercises-tests/Exercise8/Exercise8.expected
Normal file
@@ -0,0 +1,20 @@
|
||||
WARNING: Unused method getInputParameter (/Users/kraiouchkine/internal/codeql-workshop-dataflow-c/solutions/Exercise8.ql:107,13-30)
|
||||
| test.c:32:10:32:17 | access to array |
|
||||
| test.c:32:28:32:35 | access to array |
|
||||
| test.c:33:10:33:17 | access to array |
|
||||
| test.c:38:10:38:17 | access to array |
|
||||
| test.c:38:28:38:35 | access to array |
|
||||
| test.c:39:10:39:17 | access to array |
|
||||
| test.c:46:10:46:17 | access to array |
|
||||
| test.c:46:28:46:35 | access to array |
|
||||
| test.c:47:10:47:17 | access to array |
|
||||
| test.c:51:12:51:19 | access to array |
|
||||
| test.c:51:30:51:37 | access to array |
|
||||
| test.c:52:12:52:19 | access to array |
|
||||
| test.c:74:19:74:26 | access to array |
|
||||
| test.c:79:16:79:23 | access to array |
|
||||
| test.c:80:16:80:23 | access to array |
|
||||
| test.c:89:26:89:33 | access to array |
|
||||
| test.c:93:10:93:17 | access to array |
|
||||
| test.c:93:29:93:36 | access to array |
|
||||
| test.c:94:17:94:24 | access to array |
|
||||
1
exercises-tests/Exercise8/Exercise8.qlref
Normal file
1
exercises-tests/Exercise8/Exercise8.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise8.ql
|
||||
65
exercises-tests/Exercise9/Exercise9.expected
Normal file
65
exercises-tests/Exercise9/Exercise9.expected
Normal file
@@ -0,0 +1,65 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:75:21:75:25 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:10:32:14 | input | test.c:108:30:108:34 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:108:30:108:34 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:108:30:108:34 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
exercises-tests/Exercise9/Exercise9.qlref
Normal file
1
exercises-tests/Exercise9/Exercise9.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise9.ql
|
||||
7
exercises-tests/qlpack.yml
Normal file
7
exercises-tests/qlpack.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
library: false
|
||||
name: exercises-tests
|
||||
version: 0.0.1
|
||||
dependencies:
|
||||
"exercises": "*"
|
||||
extractor: cpp
|
||||
5
exercises/Exercise1.ql
Normal file
5
exercises/Exercise1.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from ArrayExpr array
|
||||
where none()
|
||||
select array, "Access of dynamic input array."
|
||||
152
exercises/Exercise10.ql
Normal file
152
exercises/Exercise10.ql
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeValidationGuardCompliant(GuardCondition gc, TypeValidationCall call) {
|
||||
typeValidationGuardOrIndirect(gc, call, _, this.getBasicBlock()) and
|
||||
typeValidationCallMatchesUse(call, this)
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
154
exercises/Exercise11.ql
Normal file
154
exercises/Exercise11.ql
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
int explorationLimit() { result = 2 }
|
||||
|
||||
module InputToAccessFlowExploration = InputToAccess::FlowExploration<explorationLimit/0>;
|
||||
|
||||
import InputToAccessFlowExploration::PartialPathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
InputToAccessFlowExploration::PartialPathNode source,
|
||||
InputToAccessFlowExploration::PartialPathNode mid, int dist
|
||||
where
|
||||
InputToAccessFlowExploration::hasPartialFlow(source, mid, dist) and
|
||||
// not a sink
|
||||
not InputToAccessConfig::isSink(mid.getNode()) and
|
||||
// no flow from mid
|
||||
not DataFlow::localFlowStep(mid.getNode(), _) and
|
||||
// more than 1 interprocedural step from source
|
||||
dist >= 1
|
||||
select mid, source, mid, "Partial flow"
|
||||
147
exercises/Exercise12.ql
Normal file
147
exercises/Exercise12.ql
Normal file
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
49
exercises/Exercise2.ql
Normal file
49
exercises/Exercise2.ql
Normal file
@@ -0,0 +1,49 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
// copy your solution from Exercise 1
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
|
||||
from DynamicInputAccess access
|
||||
where not typeValidationGuard(_, _, _, access.getBasicBlock())
|
||||
select access, "Access to dynamic input array without type validation."
|
||||
6
exercises/Exercise3.ql
Normal file
6
exercises/Exercise3.ql
Normal file
@@ -0,0 +1,6 @@
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
// replace this
|
||||
where none()
|
||||
select f, "replace this", "replace this"
|
||||
102
exercises/Exercise4.ql
Normal file
102
exercises/Exercise4.ql
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
// replace this with your solution from Exercise 2
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// replace this
|
||||
// hint: use your logic from Exercise 2
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink, "Access to dynamic input array without type validation."
|
||||
106
exercises/Exercise5.ql
Normal file
106
exercises/Exercise5.ql
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access | sink.asExpr() = access.getArrayBase())
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink, "Access to dynamic input array without type validation."
|
||||
90
exercises/Exercise7.ql
Normal file
90
exercises/Exercise7.ql
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
from DynamicInputAccess access, GuardCondition gc
|
||||
where typeValidationGuardOrIndirect(gc, _, _, access.getBasicBlock())
|
||||
select access, gc
|
||||
105
exercises/Exercise8.ql
Normal file
105
exercises/Exercise8.ql
Normal file
@@ -0,0 +1,105 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
// replace this and include mismatched validation
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
from DynamicInputAccess access
|
||||
// replace this
|
||||
where none()
|
||||
select access
|
||||
140
exercises/Exercise9.ql
Normal file
140
exercises/Exercise9.ql
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// replace this
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
6
exercises/qlpack.yml
Normal file
6
exercises/qlpack.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
library: false
|
||||
name: exercises
|
||||
version: 0.0.1
|
||||
dependencies:
|
||||
codeql/cpp-all: 0.6.1
|
||||
33
initialize-qltests.sh
Executable file
33
initialize-qltests.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script copies the test_part1.c, test_part2.c, and test_part3.c files
|
||||
# from the tests-common directory to the appropriate directories in the
|
||||
# solutions-tests and exercises-tests directories.
|
||||
[[ $(git rev-parse --show-toplevel) == $(pwd) ]] || {
|
||||
echo "This script must be run from the root of the workshop repository."
|
||||
exit 1
|
||||
}
|
||||
|
||||
SRCDIR=$(pwd)/tests-common
|
||||
|
||||
target_dirs=(
|
||||
$(pwd)/solutions-tests
|
||||
$(pwd)/exercises-tests
|
||||
)
|
||||
|
||||
for dir in "${target_dirs[@]}"; do
|
||||
# copy test-part1.c to the Exercise1-Exercise6 directories
|
||||
for i in {1..6}; do
|
||||
cp $SRCDIR/test_part1.c $dir/Exercise$i/test.c
|
||||
done
|
||||
# copy test-part2.c to the Exercise7-Exercise11 directories
|
||||
for i in {7..12}; do
|
||||
cp $SRCDIR/test_part2.c $dir/Exercise$i/test.c
|
||||
done
|
||||
# copy test-part3.c to the Exercise13-Exercise15 directories
|
||||
# for i in {13..15}; do
|
||||
# cp $SRCDIR/test_part3.c $dir/Exercise$i/test.c
|
||||
# done
|
||||
done
|
||||
|
||||
exit 0
|
||||
25
solutions-tests/Exercise1/Exercise1.expected
Normal file
25
solutions-tests/Exercise1/Exercise1.expected
Normal file
@@ -0,0 +1,25 @@
|
||||
| test.c:30:10:30:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:30:28:30:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:31:10:31:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:36:10:36:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:36:28:36:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:37:10:37:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:43:10:43:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:43:28:43:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:44:10:44:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:48:12:48:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:48:30:48:37 | access to array | Access of dynamic input array. |
|
||||
| test.c:49:12:49:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:56:10:56:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:56:28:56:35 | access to array | Access of dynamic input array. |
|
||||
| test.c:57:10:57:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:65:18:65:25 | access to array | Access of dynamic input array. |
|
||||
| test.c:66:18:66:25 | access to array | Access of dynamic input array. |
|
||||
| test.c:70:16:70:23 | access to array | Access of dynamic input array. |
|
||||
| test.c:71:16:71:23 | access to array | Access of dynamic input array. |
|
||||
| test.c:77:12:77:19 | access to array | Access of dynamic input array. |
|
||||
| test.c:77:31:77:38 | access to array | Access of dynamic input array. |
|
||||
| test.c:78:19:78:26 | access to array | Access of dynamic input array. |
|
||||
| test.c:82:10:82:17 | access to array | Access of dynamic input array. |
|
||||
| test.c:82:29:82:36 | access to array | Access of dynamic input array. |
|
||||
| test.c:83:17:83:24 | access to array | Access of dynamic input array. |
|
||||
1
solutions-tests/Exercise1/Exercise1.qlref
Normal file
1
solutions-tests/Exercise1/Exercise1.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise1.ql
|
||||
59
solutions-tests/Exercise10/Exercise10.expected
Normal file
59
solutions-tests/Exercise10/Exercise10.expected
Normal file
@@ -0,0 +1,59 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
solutions-tests/Exercise10/Exercise10.qlref
Normal file
1
solutions-tests/Exercise10/Exercise10.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise10.ql
|
||||
156
solutions-tests/Exercise11/Exercise11.expected
Normal file
156
solutions-tests/Exercise11/Exercise11.expected
Normal file
@@ -0,0 +1,156 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:31:35:31:39 | input indirection |
|
||||
| test.c:31:35:31:39 | input | test.c:31:35:31:39 | input indirection |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:31:35:31:39 | input |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input indirection | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:10:32:14 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:32:28:32:32 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:33:10:33:14 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:33:10:33:14 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:36:48:36:52 | input indirection |
|
||||
| test.c:36:48:36:52 | input | test.c:36:48:36:52 | input indirection |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:36:48:36:52 | input |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input indirection | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:10:38:14 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:38:28:38:32 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:39:10:39:14 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:45:22:45:26 | input |
|
||||
| test.c:45:3:45:27 | ... = ... | test.c:46:10:46:14 | input |
|
||||
| test.c:45:11:45:20 | call to lock_input | test.c:45:3:45:27 | ... = ... |
|
||||
| test.c:45:22:45:26 | input | test.c:45:22:45:26 | input |
|
||||
| test.c:46:10:46:14 | input | test.c:46:10:46:14 | input |
|
||||
| test.c:46:10:46:14 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:46:28:46:32 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:46:28:46:32 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:47:10:47:14 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:47:10:47:14 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:51:12:51:16 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:51:12:51:16 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:51:30:51:34 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:51:30:51:34 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:52:12:52:16 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:52:12:52:16 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:55:21:55:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:58:7:58:17 | Phi |
|
||||
| test.c:58:7:58:17 | Phi | test.c:63:10:63:14 | input |
|
||||
| test.c:63:10:63:14 | input | test.c:63:10:63:14 | input |
|
||||
| test.c:63:10:63:14 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:64:10:64:14 | input |
|
||||
| test.c:64:10:64:14 | input | test.c:64:10:64:14 | input |
|
||||
| test.c:64:10:64:14 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:70:28:70:32 | input indirection |
|
||||
| test.c:70:28:70:32 | input | test.c:70:28:70:32 | input indirection |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:70:28:70:32 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:72:18:72:22 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:72:18:72:22 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input indirection | test.c:79:16:79:20 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:72:18:72:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:72:18:72:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:72:18:72:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:73:18:73:22 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:73:18:73:22 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:74:19:74:23 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:79:16:79:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:80:16:80:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:80:16:80:20 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:84:35:84:39 | input indirection |
|
||||
| test.c:84:35:84:39 | input | test.c:84:35:84:39 | input indirection |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:84:35:84:39 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:86:12:86:16 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:86:12:86:16 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input indirection | test.c:93:10:93:14 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:12:86:16 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:12:86:16 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:12:86:16 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:86:31:86:35 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:86:31:86:35 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:89:26:89:30 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:89:26:89:30 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:10:93:14 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:104:29:104:33 | input indirection |
|
||||
| test.c:104:29:104:33 | input | test.c:104:29:104:33 | input indirection |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:104:29:104:33 | input |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:105:22:105:26 | input |
|
||||
| test.c:104:29:104:33 | input indirection | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:108:30:108:34 | input indirection |
|
||||
| test.c:108:30:108:34 | input | test.c:108:30:108:34 | input indirection |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:108:30:108:34 | input |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:109:20:109:24 | input |
|
||||
| test.c:108:30:108:34 | input indirection | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:112:37:112:41 | input indirection |
|
||||
| test.c:112:37:112:41 | input | test.c:112:37:112:41 | input indirection |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:112:37:112:41 | input |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:113:27:113:31 | input |
|
||||
| test.c:112:37:112:41 | input indirection | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:113:27:113:31 | input |
|
||||
#select
|
||||
| test.c:31:35:31:39 | input | test.c:104:29:104:33 | input | test.c:31:35:31:39 | input | Partial flow |
|
||||
| test.c:31:35:31:39 | input | test.c:108:30:108:34 | input | test.c:31:35:31:39 | input | Partial flow |
|
||||
| test.c:36:48:36:52 | input | test.c:104:29:104:33 | input | test.c:36:48:36:52 | input | Partial flow |
|
||||
| test.c:45:22:45:26 | input | test.c:104:29:104:33 | input | test.c:45:22:45:26 | input | Partial flow |
|
||||
| test.c:70:28:70:32 | input | test.c:108:30:108:34 | input | test.c:70:28:70:32 | input | Partial flow |
|
||||
| test.c:84:35:84:39 | input | test.c:112:37:112:41 | input | test.c:84:35:84:39 | input | Partial flow |
|
||||
1
solutions-tests/Exercise11/Exercise11.qlref
Normal file
1
solutions-tests/Exercise11/Exercise11.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise11.ql
|
||||
92
solutions-tests/Exercise12/Exercise12.expected
Normal file
92
solutions-tests/Exercise12/Exercise12.expected
Normal file
@@ -0,0 +1,92 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:46:10:46:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:46:28:46:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:47:10:47:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:48:19:48:23 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:51:12:51:16 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:51:30:51:34 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:52:12:52:16 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:55:21:55:25 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:65:19:65:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:48:19:48:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:55:21:55:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:65:19:65:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:46:10:46:14 | input | semmle.label | input |
|
||||
| test.c:46:28:46:32 | input | semmle.label | input |
|
||||
| test.c:47:10:47:14 | input | semmle.label | input |
|
||||
| test.c:48:19:48:23 | input | semmle.label | input |
|
||||
| test.c:51:12:51:16 | input | semmle.label | input |
|
||||
| test.c:51:30:51:34 | input | semmle.label | input |
|
||||
| test.c:52:12:52:16 | input | semmle.label | input |
|
||||
| test.c:55:21:55:25 | input | semmle.label | input |
|
||||
| test.c:65:19:65:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:75:21:75:25 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:10:32:14 | input | test.c:108:30:108:34 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:108:30:108:34 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:108:30:108:34 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:46:10:46:14 | input | test.c:104:29:104:33 | input | test.c:46:10:46:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:46:28:46:32 | input | test.c:104:29:104:33 | input | test.c:46:28:46:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:47:10:47:14 | input | test.c:104:29:104:33 | input | test.c:47:10:47:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:51:12:51:16 | input | test.c:104:29:104:33 | input | test.c:51:12:51:16 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:51:30:51:34 | input | test.c:104:29:104:33 | input | test.c:51:30:51:34 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:52:12:52:16 | input | test.c:104:29:104:33 | input | test.c:52:12:52:16 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
solutions-tests/Exercise12/Exercise12.qlref
Normal file
1
solutions-tests/Exercise12/Exercise12.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise12.ql
|
||||
14
solutions-tests/Exercise2/Exercise2.expected
Normal file
14
solutions-tests/Exercise2/Exercise2.expected
Normal file
@@ -0,0 +1,14 @@
|
||||
| test.c:30:10:30:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:35 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:23 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:23 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:17 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:36 | access to array | Access to dynamic input array without type validation. |
|
||||
| test.c:83:17:83:24 | access to array | Access to dynamic input array without type validation. |
|
||||
1
solutions-tests/Exercise2/Exercise2.qlref
Normal file
1
solutions-tests/Exercise2/Exercise2.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise2.ql
|
||||
3
solutions-tests/Exercise3/Exercise3.expected
Normal file
3
solutions-tests/Exercise3/Exercise3.expected
Normal file
@@ -0,0 +1,3 @@
|
||||
| test.c:93:5:93:15 | EP_copy_mem | test.c:93:29:93:33 | input | test.c:93:52:93:62 | input_types |
|
||||
| test.c:97:5:97:16 | EP_print_val | test.c:97:30:97:34 | input | test.c:97:53:97:63 | input_types |
|
||||
| test.c:101:5:101:23 | EP_write_val_to_mem | test.c:101:37:101:41 | input | test.c:101:60:101:70 | input_types |
|
||||
1
solutions-tests/Exercise3/Exercise3.qlref
Normal file
1
solutions-tests/Exercise3/Exercise3.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise3.ql
|
||||
77
solutions-tests/Exercise4/Exercise4.expected
Normal file
77
solutions-tests/Exercise4/Exercise4.expected
Normal file
@@ -0,0 +1,77 @@
|
||||
edges
|
||||
| test.c:29:35:29:39 | input | test.c:30:10:30:14 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:30:28:30:32 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:31:10:31:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:10:36:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:28:36:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:37:10:37:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:38:19:38:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:10:43:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:28:43:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:44:10:44:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:45:19:45:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:12:48:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:30:48:34 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:49:12:49:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:58:19:58:23 | input |
|
||||
| test.c:38:19:38:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:45:19:45:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:58:19:58:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:70:16:70:20 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:71:16:71:20 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:10:82:14 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:29:82:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:94:22:94:26 | input |
|
||||
| test.c:94:22:94:26 | input | test.c:34:48:34:52 | input |
|
||||
| test.c:97:30:97:34 | input | test.c:98:20:98:24 | input |
|
||||
| test.c:98:20:98:24 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:101:37:101:41 | input | test.c:102:27:102:31 | input |
|
||||
| test.c:102:27:102:31 | input | test.c:75:35:75:39 | input |
|
||||
nodes
|
||||
| test.c:29:35:29:39 | input | semmle.label | input |
|
||||
| test.c:30:10:30:14 | input | semmle.label | input |
|
||||
| test.c:30:28:30:32 | input | semmle.label | input |
|
||||
| test.c:31:10:31:14 | input | semmle.label | input |
|
||||
| test.c:34:48:34:52 | input | semmle.label | input |
|
||||
| test.c:36:10:36:14 | input | semmle.label | input |
|
||||
| test.c:36:28:36:32 | input | semmle.label | input |
|
||||
| test.c:37:10:37:14 | input | semmle.label | input |
|
||||
| test.c:38:19:38:23 | input | semmle.label | input |
|
||||
| test.c:43:10:43:14 | input | semmle.label | input |
|
||||
| test.c:43:28:43:32 | input | semmle.label | input |
|
||||
| test.c:44:10:44:14 | input | semmle.label | input |
|
||||
| test.c:45:19:45:23 | input | semmle.label | input |
|
||||
| test.c:48:12:48:16 | input | semmle.label | input |
|
||||
| test.c:48:30:48:34 | input | semmle.label | input |
|
||||
| test.c:49:12:49:16 | input | semmle.label | input |
|
||||
| test.c:58:19:58:23 | input | semmle.label | input |
|
||||
| test.c:63:28:63:32 | input | semmle.label | input |
|
||||
| test.c:70:16:70:20 | input | semmle.label | input |
|
||||
| test.c:71:16:71:20 | input | semmle.label | input |
|
||||
| test.c:75:35:75:39 | input | semmle.label | input |
|
||||
| test.c:82:10:82:14 | input | semmle.label | input |
|
||||
| test.c:82:29:82:33 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:94:22:94:26 | input | semmle.label | input |
|
||||
| test.c:97:30:97:34 | input | semmle.label | input |
|
||||
| test.c:98:20:98:24 | input | semmle.label | input |
|
||||
| test.c:101:37:101:41 | input | semmle.label | input |
|
||||
| test.c:102:27:102:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:30:10:30:14 | input | test.c:93:29:93:33 | input | test.c:30:10:30:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:32 | input | test.c:93:29:93:33 | input | test.c:30:28:30:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:14 | input | test.c:93:29:93:33 | input | test.c:31:10:31:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:14 | input | test.c:93:29:93:33 | input | test.c:36:10:36:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:32 | input | test.c:93:29:93:33 | input | test.c:36:28:36:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:14 | input | test.c:93:29:93:33 | input | test.c:37:10:37:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:14 | input | test.c:93:29:93:33 | input | test.c:43:10:43:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:32 | input | test.c:93:29:93:33 | input | test.c:43:28:43:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:14 | input | test.c:93:29:93:33 | input | test.c:44:10:44:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:12:48:16 | input | test.c:93:29:93:33 | input | test.c:48:12:48:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:30:48:34 | input | test.c:93:29:93:33 | input | test.c:48:30:48:34 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:49:12:49:16 | input | test.c:93:29:93:33 | input | test.c:49:12:49:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:20 | input | test.c:97:30:97:34 | input | test.c:70:16:70:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:20 | input | test.c:97:30:97:34 | input | test.c:71:16:71:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:14 | input | test.c:101:37:101:41 | input | test.c:82:10:82:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:33 | input | test.c:101:37:101:41 | input | test.c:82:29:82:33 | input | Access to dynamic input array without type validation. |
|
||||
1
solutions-tests/Exercise4/Exercise4.qlref
Normal file
1
solutions-tests/Exercise4/Exercise4.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise4.ql
|
||||
74
solutions-tests/Exercise5/Exercise5.expected
Normal file
74
solutions-tests/Exercise5/Exercise5.expected
Normal file
@@ -0,0 +1,74 @@
|
||||
edges
|
||||
| test.c:29:35:29:39 | input | test.c:30:10:30:14 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:30:28:30:32 | input |
|
||||
| test.c:29:35:29:39 | input | test.c:31:10:31:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:10:36:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:36:28:36:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:37:10:37:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:38:19:38:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:10:43:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:43:28:43:32 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:44:10:44:14 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:45:19:45:23 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:12:48:16 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:48:30:48:34 | input |
|
||||
| test.c:34:48:34:52 | input | test.c:49:12:49:16 | input |
|
||||
| test.c:38:19:38:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:45:19:45:23 | input | test.c:29:35:29:39 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:70:16:70:20 | input |
|
||||
| test.c:63:28:63:32 | input | test.c:71:16:71:20 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:10:82:14 | input |
|
||||
| test.c:75:35:75:39 | input | test.c:82:29:82:33 | input |
|
||||
| test.c:93:29:93:33 | input | test.c:94:22:94:26 | input |
|
||||
| test.c:94:22:94:26 | input | test.c:34:48:34:52 | input |
|
||||
| test.c:97:30:97:34 | input | test.c:98:20:98:24 | input |
|
||||
| test.c:98:20:98:24 | input | test.c:63:28:63:32 | input |
|
||||
| test.c:101:37:101:41 | input | test.c:102:27:102:31 | input |
|
||||
| test.c:102:27:102:31 | input | test.c:75:35:75:39 | input |
|
||||
nodes
|
||||
| test.c:29:35:29:39 | input | semmle.label | input |
|
||||
| test.c:30:10:30:14 | input | semmle.label | input |
|
||||
| test.c:30:28:30:32 | input | semmle.label | input |
|
||||
| test.c:31:10:31:14 | input | semmle.label | input |
|
||||
| test.c:34:48:34:52 | input | semmle.label | input |
|
||||
| test.c:36:10:36:14 | input | semmle.label | input |
|
||||
| test.c:36:28:36:32 | input | semmle.label | input |
|
||||
| test.c:37:10:37:14 | input | semmle.label | input |
|
||||
| test.c:38:19:38:23 | input | semmle.label | input |
|
||||
| test.c:43:10:43:14 | input | semmle.label | input |
|
||||
| test.c:43:28:43:32 | input | semmle.label | input |
|
||||
| test.c:44:10:44:14 | input | semmle.label | input |
|
||||
| test.c:45:19:45:23 | input | semmle.label | input |
|
||||
| test.c:48:12:48:16 | input | semmle.label | input |
|
||||
| test.c:48:30:48:34 | input | semmle.label | input |
|
||||
| test.c:49:12:49:16 | input | semmle.label | input |
|
||||
| test.c:63:28:63:32 | input | semmle.label | input |
|
||||
| test.c:70:16:70:20 | input | semmle.label | input |
|
||||
| test.c:71:16:71:20 | input | semmle.label | input |
|
||||
| test.c:75:35:75:39 | input | semmle.label | input |
|
||||
| test.c:82:10:82:14 | input | semmle.label | input |
|
||||
| test.c:82:29:82:33 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:94:22:94:26 | input | semmle.label | input |
|
||||
| test.c:97:30:97:34 | input | semmle.label | input |
|
||||
| test.c:98:20:98:24 | input | semmle.label | input |
|
||||
| test.c:101:37:101:41 | input | semmle.label | input |
|
||||
| test.c:102:27:102:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:30:10:30:14 | input | test.c:93:29:93:33 | input | test.c:30:10:30:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:30:28:30:32 | input | test.c:93:29:93:33 | input | test.c:30:28:30:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:31:10:31:14 | input | test.c:93:29:93:33 | input | test.c:31:10:31:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:10:36:14 | input | test.c:93:29:93:33 | input | test.c:36:10:36:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:36:28:36:32 | input | test.c:93:29:93:33 | input | test.c:36:28:36:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:37:10:37:14 | input | test.c:93:29:93:33 | input | test.c:37:10:37:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:10:43:14 | input | test.c:93:29:93:33 | input | test.c:43:10:43:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:43:28:43:32 | input | test.c:93:29:93:33 | input | test.c:43:28:43:32 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:44:10:44:14 | input | test.c:93:29:93:33 | input | test.c:44:10:44:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:12:48:16 | input | test.c:93:29:93:33 | input | test.c:48:12:48:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:48:30:48:34 | input | test.c:93:29:93:33 | input | test.c:48:30:48:34 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:49:12:49:16 | input | test.c:93:29:93:33 | input | test.c:49:12:49:16 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:70:16:70:20 | input | test.c:97:30:97:34 | input | test.c:70:16:70:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:71:16:71:20 | input | test.c:97:30:97:34 | input | test.c:71:16:71:20 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:10:82:14 | input | test.c:101:37:101:41 | input | test.c:82:10:82:14 | input | Access to dynamic input array without type validation. |
|
||||
| test.c:82:29:82:33 | input | test.c:101:37:101:41 | input | test.c:82:29:82:33 | input | Access to dynamic input array without type validation. |
|
||||
1
solutions-tests/Exercise5/Exercise5.qlref
Normal file
1
solutions-tests/Exercise5/Exercise5.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise5.ql
|
||||
20
solutions-tests/Exercise7/Exercise7.expected
Normal file
20
solutions-tests/Exercise7/Exercise7.expected
Normal file
@@ -0,0 +1,20 @@
|
||||
WARNING: Unused method getInputParameter (/Users/kraiouchkine/internal/codeql-workshop-dataflow-c/solutions/Exercise7.ql:84,13-30)
|
||||
| test.c:32:10:32:17 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:32:10:32:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:32:10:32:17 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:32:28:32:35 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:53:14:54:24 | ... == ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:33:10:33:17 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:63:10:63:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:63:28:63:35 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:64:10:64:17 | access to array | test.c:58:7:58:75 | ... != ... |
|
||||
| test.c:72:18:72:25 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:73:18:73:25 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:74:19:74:26 | access to array | test.c:71:7:71:76 | ... == ... |
|
||||
| test.c:86:12:86:19 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:86:31:86:38 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:87:19:87:26 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
| test.c:89:26:89:33 | access to array | test.c:85:7:85:75 | ... == ... |
|
||||
1
solutions-tests/Exercise7/Exercise7.qlref
Normal file
1
solutions-tests/Exercise7/Exercise7.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise7.ql
|
||||
20
solutions-tests/Exercise8/Exercise8.expected
Normal file
20
solutions-tests/Exercise8/Exercise8.expected
Normal file
@@ -0,0 +1,20 @@
|
||||
WARNING: Unused method getInputParameter (/Users/kraiouchkine/internal/codeql-workshop-dataflow-c/solutions/Exercise8.ql:107,13-30)
|
||||
| test.c:32:10:32:17 | access to array |
|
||||
| test.c:32:28:32:35 | access to array |
|
||||
| test.c:33:10:33:17 | access to array |
|
||||
| test.c:38:10:38:17 | access to array |
|
||||
| test.c:38:28:38:35 | access to array |
|
||||
| test.c:39:10:39:17 | access to array |
|
||||
| test.c:46:10:46:17 | access to array |
|
||||
| test.c:46:28:46:35 | access to array |
|
||||
| test.c:47:10:47:17 | access to array |
|
||||
| test.c:51:12:51:19 | access to array |
|
||||
| test.c:51:30:51:37 | access to array |
|
||||
| test.c:52:12:52:19 | access to array |
|
||||
| test.c:74:19:74:26 | access to array |
|
||||
| test.c:79:16:79:23 | access to array |
|
||||
| test.c:80:16:80:23 | access to array |
|
||||
| test.c:89:26:89:33 | access to array |
|
||||
| test.c:93:10:93:17 | access to array |
|
||||
| test.c:93:29:93:36 | access to array |
|
||||
| test.c:94:17:94:24 | access to array |
|
||||
1
solutions-tests/Exercise8/Exercise8.qlref
Normal file
1
solutions-tests/Exercise8/Exercise8.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise8.ql
|
||||
65
solutions-tests/Exercise9/Exercise9.expected
Normal file
65
solutions-tests/Exercise9/Exercise9.expected
Normal file
@@ -0,0 +1,65 @@
|
||||
edges
|
||||
| test.c:31:35:31:39 | input | test.c:32:10:32:14 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:32:28:32:32 | input |
|
||||
| test.c:31:35:31:39 | input | test.c:33:10:33:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:10:38:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:38:28:38:32 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:39:10:39:14 | input |
|
||||
| test.c:36:48:36:52 | input | test.c:40:19:40:23 | input |
|
||||
| test.c:40:19:40:23 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:74:19:74:23 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:75:21:75:25 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:79:16:79:20 | input |
|
||||
| test.c:70:28:70:32 | input | test.c:80:16:80:20 | input |
|
||||
| test.c:75:21:75:25 | input | test.c:31:35:31:39 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:89:26:89:30 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:10:93:14 | input |
|
||||
| test.c:84:35:84:39 | input | test.c:93:29:93:33 | input |
|
||||
| test.c:104:29:104:33 | input | test.c:105:22:105:26 | input |
|
||||
| test.c:105:22:105:26 | input | test.c:36:48:36:52 | input |
|
||||
| test.c:108:30:108:34 | input | test.c:109:20:109:24 | input |
|
||||
| test.c:109:20:109:24 | input | test.c:70:28:70:32 | input |
|
||||
| test.c:112:37:112:41 | input | test.c:113:27:113:31 | input |
|
||||
| test.c:113:27:113:31 | input | test.c:84:35:84:39 | input |
|
||||
nodes
|
||||
| test.c:31:35:31:39 | input | semmle.label | input |
|
||||
| test.c:32:10:32:14 | input | semmle.label | input |
|
||||
| test.c:32:28:32:32 | input | semmle.label | input |
|
||||
| test.c:33:10:33:14 | input | semmle.label | input |
|
||||
| test.c:36:48:36:52 | input | semmle.label | input |
|
||||
| test.c:38:10:38:14 | input | semmle.label | input |
|
||||
| test.c:38:28:38:32 | input | semmle.label | input |
|
||||
| test.c:39:10:39:14 | input | semmle.label | input |
|
||||
| test.c:40:19:40:23 | input | semmle.label | input |
|
||||
| test.c:70:28:70:32 | input | semmle.label | input |
|
||||
| test.c:74:19:74:23 | input | semmle.label | input |
|
||||
| test.c:75:21:75:25 | input | semmle.label | input |
|
||||
| test.c:79:16:79:20 | input | semmle.label | input |
|
||||
| test.c:80:16:80:20 | input | semmle.label | input |
|
||||
| test.c:84:35:84:39 | input | semmle.label | input |
|
||||
| test.c:89:26:89:30 | input | semmle.label | input |
|
||||
| test.c:93:10:93:14 | input | semmle.label | input |
|
||||
| test.c:93:29:93:33 | input | semmle.label | input |
|
||||
| test.c:104:29:104:33 | input | semmle.label | input |
|
||||
| test.c:105:22:105:26 | input | semmle.label | input |
|
||||
| test.c:108:30:108:34 | input | semmle.label | input |
|
||||
| test.c:109:20:109:24 | input | semmle.label | input |
|
||||
| test.c:112:37:112:41 | input | semmle.label | input |
|
||||
| test.c:113:27:113:31 | input | semmle.label | input |
|
||||
subpaths
|
||||
#select
|
||||
| test.c:32:10:32:14 | input | test.c:104:29:104:33 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:10:32:14 | input | test.c:108:30:108:34 | input | test.c:32:10:32:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:104:29:104:33 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:32:28:32:32 | input | test.c:108:30:108:34 | input | test.c:32:28:32:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:104:29:104:33 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:33:10:33:14 | input | test.c:108:30:108:34 | input | test.c:33:10:33:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:10:38:14 | input | test.c:104:29:104:33 | input | test.c:38:10:38:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:38:28:38:32 | input | test.c:104:29:104:33 | input | test.c:38:28:38:32 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:39:10:39:14 | input | test.c:104:29:104:33 | input | test.c:39:10:39:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:74:19:74:23 | input | test.c:108:30:108:34 | input | test.c:74:19:74:23 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:79:16:79:20 | input | test.c:108:30:108:34 | input | test.c:79:16:79:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:80:16:80:20 | input | test.c:108:30:108:34 | input | test.c:80:16:80:20 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:89:26:89:30 | input | test.c:112:37:112:41 | input | test.c:89:26:89:30 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:10:93:14 | input | test.c:112:37:112:41 | input | test.c:93:10:93:14 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
| test.c:93:29:93:33 | input | test.c:112:37:112:41 | input | test.c:93:29:93:33 | input | Access to dynamic input array with missing or mismatched type validation. |
|
||||
1
solutions-tests/Exercise9/Exercise9.qlref
Normal file
1
solutions-tests/Exercise9/Exercise9.qlref
Normal file
@@ -0,0 +1 @@
|
||||
Exercise9.ql
|
||||
8
solutions-tests/qlpack.yml
Normal file
8
solutions-tests/qlpack.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
library: false
|
||||
name: solutions-tests
|
||||
version: 0.0.1
|
||||
dependencies:
|
||||
"solutions": "*"
|
||||
extractor: cpp
|
||||
tests: .
|
||||
5
solutions/Exercise1.ql
Normal file
5
solutions/Exercise1.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from ArrayExpr array
|
||||
where array.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
select array, "Access of dynamic input array."
|
||||
155
solutions/Exercise10.ql
Normal file
155
solutions/Exercise10.ql
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeValidationGuardCompliant(GuardCondition gc, TypeValidationCall call) {
|
||||
typeValidationGuardOrIndirect(gc, call, _, this.getBasicBlock()) and
|
||||
typeValidationCallMatchesUse(call, this)
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(FunctionCall fc, DynamicInputAccess access, GuardCondition gc |
|
||||
node.asExpr() = fc.getAnArgument() and
|
||||
access.isTypeValidationGuardCompliant(gc, _) and
|
||||
typeValidationGuard(gc, _, _, node.asExpr().getBasicBlock())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
154
solutions/Exercise11.ql
Normal file
154
solutions/Exercise11.ql
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
int explorationLimit() { result = 2 }
|
||||
|
||||
module InputToAccessFlowExploration = InputToAccess::FlowExploration<explorationLimit/0>;
|
||||
|
||||
import InputToAccessFlowExploration::PartialPathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
InputToAccessFlowExploration::PartialPathNode source,
|
||||
InputToAccessFlowExploration::PartialPathNode mid, int dist
|
||||
where
|
||||
InputToAccessFlowExploration::hasPartialFlow(source, mid, dist) and
|
||||
// not a sink
|
||||
not InputToAccessConfig::isSink(mid.getNode()) and
|
||||
// no flow from mid
|
||||
not DataFlow::localFlowStep(mid.getNode(), _) and
|
||||
// more than 1 interprocedural step from source
|
||||
dist >= 1
|
||||
select mid, source, mid, "Partial flow"
|
||||
150
solutions/Exercise12.ql
Normal file
150
solutions/Exercise12.ql
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(FunctionCall fc |
|
||||
fc.getTarget().hasName("lock_input") and
|
||||
fc.getArgument(0) = node1.asExpr() and
|
||||
fc = node2.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
47
solutions/Exercise2.ql
Normal file
47
solutions/Exercise2.ql
Normal file
@@ -0,0 +1,47 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true)
|
||||
)
|
||||
}
|
||||
|
||||
from DynamicInputAccess access
|
||||
where not typeValidationGuard(_, _, _, access.getBasicBlock())
|
||||
select access, "Access to dynamic input array without type validation."
|
||||
5
solutions/Exercise3.ql
Normal file
5
solutions/Exercise3.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Function f
|
||||
where f.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"])
|
||||
select f, f.getParameter(0), f.getParameter(1)
|
||||
104
solutions/Exercise4.ql
Normal file
104
solutions/Exercise4.ql
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
not typeValidationGuard(_, _, _, access.getBasicBlock())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink, "Access to dynamic input array without type validation."
|
||||
105
solutions/Exercise5.ql
Normal file
105
solutions/Exercise5.ql
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access | sink.asExpr() = access.getArrayBase())
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
typeValidationGuard(_, _, _, node.asExpr().getBasicBlock())
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink, "Access to dynamic input array without type validation."
|
||||
91
solutions/Exercise7.ql
Normal file
91
solutions/Exercise7.ql
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
from DynamicInputAccess access, GuardCondition gc
|
||||
where typeValidationGuardOrIndirect(gc, _, _, access.getBasicBlock())
|
||||
select access, gc
|
||||
114
solutions/Exercise8.ql
Normal file
114
solutions/Exercise8.ql
Normal file
@@ -0,0 +1,114 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
from DynamicInputAccess access
|
||||
where access.isTypeNotValidated()
|
||||
select access
|
||||
142
solutions/Exercise9.ql
Normal file
142
solutions/Exercise9.ql
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @id cpp/check-type-before-use
|
||||
* @name Check type before use
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
int dyn_input_type_mem() { result = 1 }
|
||||
|
||||
int dyn_input_type_val() { result = 2 }
|
||||
|
||||
predicate typeValidationCallMatchesUse(TypeValidationCall call, DynamicInputAccess use) {
|
||||
exists(FieldAccess f, int expected |
|
||||
expected = call.getExpectedInputType(use.getArrayOffset().getValue().toInt()) and
|
||||
f.getQualifier() = use and
|
||||
(
|
||||
expected = dyn_input_type_mem() and f.getTarget().getName() = "ptr"
|
||||
or
|
||||
expected = dyn_input_type_val() and f.getTarget().getName() = "val"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An access of a dynamic input array (of type `dyn_input_t`)
|
||||
*/
|
||||
class DynamicInputAccess extends ArrayExpr {
|
||||
DynamicInputAccess() {
|
||||
this.getArrayBase().getType().(DerivedType).getBaseType().getName() = "dyn_input_t"
|
||||
}
|
||||
|
||||
predicate isTypeNotValidated() {
|
||||
not typeValidationGuardOrIndirect(_, _, _, this.getBasicBlock())
|
||||
or
|
||||
exists(TypeValidationCall call |
|
||||
typeValidationGuardOrIndirect(_, call, _, this.getBasicBlock()) and
|
||||
not typeValidationCallMatchesUse(call, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DYN_INPUT_TYPE`
|
||||
*/
|
||||
class TypeValidationCall extends FunctionCall {
|
||||
TypeValidationCall() { this.getTarget().hasName("DYN_INPUT_TYPE") }
|
||||
|
||||
int getExpectedInputType(int input_index) {
|
||||
result = this.getArgument(input_index).getValue().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `op1` and `op2` are checked for equality in any order
|
||||
* with no distinction between left and right operands of the equality check
|
||||
*/
|
||||
predicate guardEnsuresEqUnordered(
|
||||
Expr op1, Expr op2, GuardCondition guard, BasicBlock block, boolean areEqual
|
||||
) {
|
||||
guard.ensuresEq(op1, op2, 0, block, areEqual) or
|
||||
guard.ensuresEq(op2, op1, 0, block, areEqual)
|
||||
}
|
||||
|
||||
/**
|
||||
* Relates a `call` to a `guard`, which uses the result of the call to validate
|
||||
* equality of the result of `call` against `other` to guard `block`.
|
||||
*/
|
||||
predicate typeValidationGuard(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
exists(Expr dest |
|
||||
DataFlow::localExprFlow(call, dest) and
|
||||
guardEnsuresEqUnordered(dest, other, guard, block, true) and
|
||||
InputTypesToTypeValidation::hasFlowToExpr(other)
|
||||
)
|
||||
}
|
||||
|
||||
predicate typeValidationGuardOrIndirect(
|
||||
GuardCondition guard, TypeValidationCall call, Expr other, BasicBlock block
|
||||
) {
|
||||
typeValidationGuard(guard, call, other, block) or
|
||||
typeValidationGuardOrIndirect(guard, call, other,
|
||||
block.getEnclosingFunction().getACallToThisFunction().getBasicBlock())
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input_types` parameter to a subsequent use in a GuardCondition.
|
||||
*/
|
||||
module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
|
||||
|
||||
module InputTypesToTypeValidationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction f | f.getInputTypesParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
// avoid non-monotonic recursion, as `typeValidationGuard` depends on this config
|
||||
sink.asExpr() instanceof VariableAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An entrypoint that has a `dyn_array_t[2]` `input` parameter and
|
||||
* `input_types` parameter.
|
||||
*/
|
||||
class EntrypointFunction extends Function {
|
||||
EntrypointFunction() { this.hasName(["EP_copy_mem", "EP_print_val", "EP_write_val_to_mem"]) }
|
||||
|
||||
Parameter getInputParameter() { result = this.getParameter(0) }
|
||||
|
||||
Parameter getInputTypesParameter() { result = this.getParameter(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A global data-flow configuration tracking flow from an entrypoint's
|
||||
* `input` parameter to a subsequent `ArrayExpr` access.
|
||||
*/
|
||||
module InputToAccess = DataFlow::Make<InputToAccessConfig>;
|
||||
|
||||
import InputToAccess::PathGraph
|
||||
|
||||
module InputToAccessConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(EntrypointFunction ep | ep.getInputParameter() = source.asParameter())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DynamicInputAccess access |
|
||||
sink.asExpr() = access.getArrayBase() and
|
||||
access.isTypeNotValidated()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from InputToAccess::PathNode source, InputToAccess::PathNode sink
|
||||
where InputToAccess::hasFlowPath(source, sink)
|
||||
select sink, source, sink,
|
||||
"Access to dynamic input array with missing or mismatched type validation."
|
||||
6
solutions/qlpack.yml
Normal file
6
solutions/qlpack.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
library: false
|
||||
name: solutions
|
||||
version: 0.0.1
|
||||
dependencies:
|
||||
codeql/cpp-all: 0.6.1
|
||||
103
tests-common/test_part1.c
Normal file
103
tests-common/test_part1.c
Normal file
@@ -0,0 +1,103 @@
|
||||
typedef unsigned long size_t;
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
int printf(const char *format, ...);
|
||||
|
||||
#define DYN_INPUT_TYPE_NONE 0x0
|
||||
#define DYN_INPUT_TYPE_MEM 0x1
|
||||
#define DYN_INPUT_TYPE_VAL 0x2
|
||||
|
||||
typedef union dyn_input {
|
||||
int val;
|
||||
struct {
|
||||
void *buf;
|
||||
size_t size;
|
||||
} ptr;
|
||||
} dyn_input_t;
|
||||
|
||||
/**
|
||||
* A helper function which returns a packed unsigned integer value representing
|
||||
* a dynamic input type, where `p0` is the type of the first input and `p1` is
|
||||
* the type of the second input.
|
||||
*/
|
||||
unsigned int DYN_INPUT_TYPE(unsigned int p0, unsigned int p1) {
|
||||
return ((p0) | ((p1) << 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions called from entrypoints that receive and process dynamic inputs.
|
||||
*/
|
||||
void copy_mem_nested(dyn_input_t *input) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // path-dependent
|
||||
}
|
||||
|
||||
int copy_mem(unsigned int unused, dyn_input_t *input,
|
||||
unsigned int input_types) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - type not checked
|
||||
copy_mem_nested(input); // NON_COMPLIANT - type not checked
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
}
|
||||
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - guard doesn't control all paths
|
||||
copy_mem_nested(input); // NON_COMPLIANT - guard doesn't control all paths
|
||||
|
||||
if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM) == 100) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - useless type check
|
||||
}
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // COMPLIANT - type checked
|
||||
copy_mem_nested(input); // COMPLIANT - type checked
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_val(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_NONE)) {
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_val_to_mem(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_MEM)) {
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // COMPLIANT - type checked
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entrypoints that have the following parameters:
|
||||
* 1. An array, `input`, of two dyn_input_t dynamic inputs
|
||||
* 2. An unsigned int, `input_types`, describing the type of each input to be
|
||||
* compared against `DYN_INPUT_TYPE`.
|
||||
*/
|
||||
int EP_copy_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return copy_mem(0, input, input_types);
|
||||
}
|
||||
|
||||
int EP_print_val(dyn_input_t input[2], unsigned int input_types) {
|
||||
return print_val(input, input_types);
|
||||
}
|
||||
|
||||
int EP_write_val_to_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return write_val_to_mem(input, input_types);
|
||||
}
|
||||
114
tests-common/test_part2.c
Normal file
114
tests-common/test_part2.c
Normal file
@@ -0,0 +1,114 @@
|
||||
typedef unsigned long size_t;
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
int printf(const char *format, ...);
|
||||
|
||||
#define DYN_INPUT_TYPE_NONE 0x0
|
||||
#define DYN_INPUT_TYPE_MEM 0x1
|
||||
#define DYN_INPUT_TYPE_VAL 0x2
|
||||
|
||||
typedef union dyn_input {
|
||||
int val;
|
||||
struct {
|
||||
void *buf;
|
||||
size_t size;
|
||||
} ptr;
|
||||
} dyn_input_t;
|
||||
|
||||
dyn_input_t *lock_input(const dyn_input_t *input);
|
||||
|
||||
/**
|
||||
* A helper function which returns a packed unsigned integer value representing
|
||||
* a dynamic input type, where `p0` is the type of the first input and `p1` is
|
||||
* the type of the second input.
|
||||
*/
|
||||
unsigned int DYN_INPUT_TYPE(unsigned int p0, unsigned int p1) {
|
||||
return ((p0) | ((p1) << 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions called from entrypoints that receive and process dynamic inputs.
|
||||
*/
|
||||
void copy_mem_nested(dyn_input_t *input) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // path-dependent
|
||||
}
|
||||
|
||||
int copy_mem(unsigned int unused, dyn_input_t *input,
|
||||
unsigned int input_types) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - type not checked
|
||||
copy_mem_nested(input); // NON_COMPLIANT - type not checked
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
}
|
||||
|
||||
input = lock_input(input);
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - guard doesn't control all paths
|
||||
copy_mem_nested(input); // NON_COMPLIANT - guard doesn't control all paths
|
||||
|
||||
if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM) == 100) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - invalid type check
|
||||
} else if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_MEM) ==
|
||||
input_types) {
|
||||
copy_mem_nested(input); // NON_COMPLIANT - mismatched type for input[0]
|
||||
}
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
// valid fail-fast type check
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // COMPLIANT - type checked
|
||||
copy_mem_nested(input); // COMPLIANT - type checked
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_val(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_NONE)) {
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
printf("%zu", input[0].ptr.size); // NON_COMPLIANT - mismatched type
|
||||
copy_mem_nested(input); // NON_COMPLIANT - mismatched type
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_val_to_mem(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_MEM)) {
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // COMPLIANT - type checked
|
||||
(void)(*(
|
||||
unsigned char *)(input[0].ptr.buf)); // NON_COMPLIANT - mismatched type
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entrypoints that have the following parameters:
|
||||
* 1. An array, `input`, of two dyn_input_t dynamic inputs
|
||||
* 2. An unsigned int, `input_types`, describing the type of each input to be
|
||||
* compared against `DYN_INPUT_TYPE`.
|
||||
*/
|
||||
int EP_copy_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return copy_mem(0, input, input_types);
|
||||
}
|
||||
|
||||
int EP_print_val(dyn_input_t input[2], unsigned int input_types) {
|
||||
return print_val(input, input_types);
|
||||
}
|
||||
|
||||
int EP_write_val_to_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return write_val_to_mem(input, input_types);
|
||||
}
|
||||
114
tests-common/test_part3.c
Normal file
114
tests-common/test_part3.c
Normal file
@@ -0,0 +1,114 @@
|
||||
typedef unsigned long size_t;
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
int printf(const char *format, ...);
|
||||
|
||||
#define DYN_INPUT_TYPE_NONE 0x0
|
||||
#define DYN_INPUT_TYPE_MEM 0x1
|
||||
#define DYN_INPUT_TYPE_VAL 0x2
|
||||
|
||||
typedef union dyn_input {
|
||||
int val;
|
||||
struct {
|
||||
void *buf;
|
||||
size_t size;
|
||||
} ptr;
|
||||
} dyn_input_t;
|
||||
|
||||
dyn_input_t *lock_input(const dyn_input_t *input);
|
||||
|
||||
/**
|
||||
* A helper function which returns a packed unsigned integer value representing
|
||||
* a dynamic input type, where `p0` is the type of the first input and `p1` is
|
||||
* the type of the second input.
|
||||
*/
|
||||
unsigned int DYN_INPUT_TYPE(unsigned int p0, unsigned int p1) {
|
||||
return ((p0) | ((p1) << 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions called from entrypoints that receive and process dynamic inputs.
|
||||
*/
|
||||
void copy_mem_nested(dyn_input_t *input) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // path-dependent
|
||||
}
|
||||
|
||||
int copy_mem(unsigned int unused, dyn_input_t *input,
|
||||
unsigned int input_types) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - type not checked
|
||||
copy_mem_nested(input); // NON_COMPLIANT - type not checked
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
}
|
||||
|
||||
input = lock_input(input);
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - guard doesn't control all paths
|
||||
copy_mem_nested(input); // NON_COMPLIANT - guard doesn't control all paths
|
||||
|
||||
if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM) == 100) {
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // NON_COMPLIANT - invalid type check
|
||||
} else if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_MEM) ==
|
||||
input_types) {
|
||||
copy_mem_nested(input); // NON_COMPLIANT - mismatched type for input[0]
|
||||
}
|
||||
|
||||
if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) {
|
||||
// valid fail-fast type check
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(input[0].ptr.buf, input[1].ptr.buf,
|
||||
input[1].ptr.size); // COMPLIANT - type checked
|
||||
copy_mem_nested(input); // COMPLIANT - type checked
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_val(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_NONE)) {
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
printf("%d", input[0].val++); // COMPLIANT - type checked
|
||||
printf("%zu", input[0].ptr.size); // NON_COMPLIANT - mismatched type
|
||||
copy_mem_nested(input); // NON_COMPLIANT - mismatched type
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
printf("%d", input[0].val++); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_val_to_mem(dyn_input_t *input, unsigned int input_types) {
|
||||
if (input_types == DYN_INPUT_TYPE(DYN_INPUT_TYPE_VAL, DYN_INPUT_TYPE_MEM)) {
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // COMPLIANT - type checked
|
||||
(void)(*(
|
||||
unsigned char *)(input[0].ptr.buf)); // NON_COMPLIANT - mismatched type
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(input[1].ptr.buf, &input[0].val,
|
||||
sizeof(input[0].val)); // NON_COMPLIANT - type not checked
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Entrypoints that have the following parameters:
|
||||
* 1. An array, `input`, of two dyn_input_t dynamic inputs
|
||||
* 2. An unsigned int, `input_types`, describing the type of each input to be
|
||||
* compared against `DYN_INPUT_TYPE`.
|
||||
*/
|
||||
int EP_copy_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return copy_mem(0, input, input_types);
|
||||
}
|
||||
|
||||
int EP_print_val(dyn_input_t input[2], unsigned int input_types) {
|
||||
return print_val(input, input_types);
|
||||
}
|
||||
|
||||
int EP_write_val_to_mem(dyn_input_t input[2], unsigned int input_types) {
|
||||
return write_val_to_mem(input, input_types);
|
||||
}
|
||||
Reference in New Issue
Block a user