C++: Implement FormattingFunction isOutputStream, isOutputString so that subclasses don't need to be accessed for this information, and can be private.

This commit is contained in:
Geoffrey White
2020-11-05 13:23:32 +00:00
parent 99b01e7d36
commit c3b16a5fd2
4 changed files with 31 additions and 12 deletions

View File

@@ -11,7 +11,7 @@ import semmle.code.cpp.models.interfaces.Alias
/**
* The standard functions `printf`, `wprintf` and their glib variants.
*/
class Printf extends FormattingFunction, AliasFunction {
private class Printf extends FormattingFunction, AliasFunction {
Printf() {
this instanceof TopLevelFunction and
(
@@ -31,6 +31,8 @@ class Printf extends FormattingFunction, AliasFunction {
hasGlobalName("wprintf_s")
}
override predicate isOutputGlobal() { any() }
override predicate parameterNeverEscapes(int n) { n = 0 }
override predicate parameterEscapesOnlyViaReturn(int n) { none() }
@@ -41,7 +43,7 @@ class Printf extends FormattingFunction, AliasFunction {
/**
* The standard functions `fprintf`, `fwprintf` and their glib variants.
*/
class Fprintf extends FormattingFunction {
private class Fprintf extends FormattingFunction {
Fprintf() {
this instanceof TopLevelFunction and
(
@@ -57,6 +59,8 @@ class Fprintf extends FormattingFunction {
deprecated override predicate isWideCharDefault() { hasGlobalOrStdName("fwprintf") }
override int getOutputParameterIndex() { result = 0 }
override predicate isOutputStream() { any() }
}
/**
@@ -232,7 +236,7 @@ private class StringCchPrintf extends FormattingFunction {
/**
* The standard function `syslog`.
*/
class Syslog extends FormattingFunction {
private class Syslog extends FormattingFunction {
Syslog() {
this instanceof TopLevelFunction and
hasGlobalName("syslog") and
@@ -240,4 +244,6 @@ class Syslog extends FormattingFunction {
}
override int getFormatParameterIndex() { result = 1 }
override predicate isOutputGlobal() { any() }
}

View File

@@ -109,9 +109,24 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
}
/**
* Gets the position at which the output parameter, if any, occurs.
* Gets the position at which the output parameter, if any, occurs. This may
* be a buffer that characters are written to if this function behaves like
* `sprintf`. Alternatively it may be a stream that is used for output if
* this function behaves like `fprintf` (see `isOutputStream`).
*/
int getOutputParameterIndex() { none() }
/**
* Holds if this function outputs to a global stream such as standard output,
* standard error or a system log. For example `printf`.
*/
predicate isOutputGlobal() { none() }
/**
* Holds if this function outputs to the stream indicated by
* `getOutputParameterIndex()`, that is, this function behaves like `fprintf`.
*/
predicate isOutputStream() { none() }
/**
* Gets the position of the first format argument, corresponding with

View File

@@ -3,7 +3,6 @@
*/
import cpp
import semmle.code.cpp.models.implementations.Printf
/**
* A function call that writes to a file.
@@ -144,8 +143,9 @@ private predicate fileWrite(Call write, Expr source, Expr dest) {
)
or
// fprintf
s >= f.(Fprintf).getFormatParameterIndex() and
d = f.(Fprintf).getOutputParameterIndex()
f.(FormattingFunction).isOutputStream() and
s >= f.(FormattingFunction).getFormatParameterIndex() and
d = f.(FormattingFunction).getOutputParameterIndex()
)
or
// file stream using '<<', 'put' or 'write'

View File

@@ -59,11 +59,9 @@ private predicate outputWrite(Expr write, Expr source) {
exists(Function f, int arg |
f = write.(Call).getTarget() and source = write.(Call).getArgument(arg)
|
// printf
arg >= f.(Printf).getFormatParameterIndex()
or
// syslog
arg >= f.(Syslog).getFormatParameterIndex()
// printf / syslog
f.(FormattingFunction).isOutputGlobal() and
arg >= f.(FormattingFunction).getFormatParameterIndex()
or
// puts, putchar
(