CodeQL for C/C++
.. rst-class:: setup
For this example you need to set up CodeQL for Visual Studio Code and download the CodeQL database for rsyslog from GitHub.
.. rst-class:: build
printf: Returns number of characters printed.printf("Hello %s!", name)
sprintf: Returns number of characters written tobuf.sprintf(buf, "Hello %s!", name)
snprintf: Returns number of characters it would have written tobufhadnbeen sufficiently large, not the number of characters actually written.snprintf(buf, n, "Hello %s!", name)
In pre-C99 versions of glibc
snprintfwould return -1 ifnwas too small!
Vulnerable code looked similar to this (original):
char buf[1024]; int pos = 0; for (int i = 0; i < n; i++) { pos += snprintf(buf + pos, sizeof(buf) - pos, "%s", strs[i]); }
Disclosed as CVE-2018-1000140.
Blog post: https://securitylab.github.com/research/librelp-buffer-overflow-cve-2018-1000140
Write a query to find calls to
snprintfHint: Use class
FunctionCallRestrict to calls whose result is used
Hint: Use class
ExprInVoidContextRestrict to calls where the format string contains “%s”
Hint: Use predicates
Expr.getValueandstring.regexpMatchRestrict to calls where the result flows back to the size argument
Hint: Import library
semmle.code.cpp.dataflow.TaintTrackingand use predicateTaintTracking::localTaint
.. literalinclude:: ../query-examples/cpp/snprintf-1.ql :language: ql
.. rst-class:: build
Note
The regular expression for matching the format string uses the “(?s)” directive to ensure that “.” also matches any newline characters embedded in the string.