/** * @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") } } /** * Holds if `i` is an endianness conversion. * (A telltale sign of network data.) */ predicate isNetworkData(Instruction i) { i.(CallInstruction).getCallTarget().(FunctionInstruction).getFunctionSymbol() instanceof EndianConvert } /** Holds if `i` is a narrowing conversion. */ predicate isNarrowingConversion(ConvertInstruction i) { i.getResultSize() < i.getUnary().getResultSize() } class Cfg extends TaintTracking::Configuration { Cfg() { this = "FizzOverflowIR" } /** * Holds if `source` is network data. */ override predicate isSource(DataFlow::Node source) { isNetworkData(source.asInstruction()) } /** Holds if `sink` is a narrowing conversion. */ override predicate isSink(DataFlow::Node sink) { isNarrowingConversion(sink.asInstruction()) } } 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 + "."