/** * @name Fizz Overflow * @description Narrowing conversions on untrusted data could enable * an attacker to trigger an integer overflow. * @kind path-problem * @problem.severity warning */ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.ir.IR import DataFlow::PathGraph /** * The endianness conversion function `Endian::big()`. * It is Folly's replacement for `ntohs` and `ntohl`. */ class EndianConvert extends Function { EndianConvert() { this.getName() = "big" and this.getDeclaringType().getName().matches("Endian") } } class Cfg extends TaintTracking::Configuration { Cfg() { this = "FizzOverflowIR" } /** Holds if `source` is a call to `Endian::big()`. */ override predicate isSource(DataFlow::Node source) { source .asInstruction() .(CallInstruction) .getCallTarget() .(FunctionInstruction) .getFunctionSymbol() instanceof EndianConvert } /** Holds if `sink` is a narrowing conversion. */ override predicate isSink(DataFlow::Node sink) { sink.asInstruction().getResultSize() < sink .asInstruction() .(ConvertInstruction) .getUnary() .getResultSize() } } from Cfg cfg, DataFlow::PathNode source, DataFlow::PathNode sink, ConvertInstruction conv, Type inputType, Type outputType where cfg.hasFlowPath(source, sink) and conv = sink.getNode().asInstruction() and inputType = conv.getUnary().getResultType() and outputType = conv.getResultType() select sink, source, sink, "Conversion of untrusted data from " + inputType + " to " + outputType + "."