/** * @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; 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; 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."