diff --git a/ql/src/semmle/go/frameworks/Stdlib.qll b/ql/src/semmle/go/frameworks/Stdlib.qll index cee1e59676d..82210dce29b 100644 --- a/ql/src/semmle/go/frameworks/Stdlib.qll +++ b/ql/src/semmle/go/frameworks/Stdlib.qll @@ -146,35 +146,6 @@ module Fmt { } } -/** Provides models of commonly used functions in the `io/ioutil` package. */ -module IoUtil { - private class IoUtilFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode { - IoUtilFileSystemAccess() { - exists(string fn | getTarget().hasQualifiedName("io/ioutil", fn) | - fn = "ReadDir" or - fn = "ReadFile" or - fn = "TempDir" or - fn = "TempFile" or - fn = "WriteFile" - ) - } - - override DataFlow::Node getAPathArgument() { result = getAnArgument() } - } - - /** - * A taint model of the `ioutil.ReadAll` function, recording that it propagates taint - * from its first argument to its first result. - */ - private class ReadAll extends TaintTracking::FunctionModel { - ReadAll() { hasQualifiedName("io/ioutil", "ReadAll") } - - override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) { - inp.isParameter(0) and outp.isResult(0) - } - } -} - /** Provides models of commonly used functions in the `os` package. */ module OS { /** diff --git a/ql/src/semmle/go/frameworks/stdlib/IoIoutil.qll b/ql/src/semmle/go/frameworks/stdlib/IoIoutil.qll new file mode 100644 index 00000000000..e59de928049 --- /dev/null +++ b/ql/src/semmle/go/frameworks/stdlib/IoIoutil.qll @@ -0,0 +1,56 @@ +/** + * Provides classes modeling security-relevant aspects of the `io/ioutil` package. + */ + +import go + +/** Provides models of commonly used functions in the `io/ioutil` package. */ +module IoIoutil { + private class IoUtilFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode { + IoUtilFileSystemAccess() { + exists(string fn | getTarget().hasQualifiedName("io/ioutil", fn) | + fn = "ReadDir" or + fn = "ReadFile" or + fn = "TempDir" or + fn = "TempFile" or + fn = "WriteFile" + ) + } + + override DataFlow::Node getAPathArgument() { result = getAnArgument() } + } + + private class FunctionModels extends TaintTracking::FunctionModel { + FunctionInput inp; + FunctionOutput outp; + + FunctionModels() { + // signature: func NopCloser(r io.Reader) io.ReadCloser + hasQualifiedName("io/ioutil", "NopCloser") and + (inp.isParameter(0) and outp.isResult()) + or + // signature: func ReadAll(r io.Reader) ([]byte, error) + hasQualifiedName("io/ioutil", "ReadAll") and + (inp.isParameter(0) and outp.isResult(0)) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } + + private class MethodModels extends TaintTracking::FunctionModel, Method { + FunctionInput inp; + FunctionOutput outp; + + MethodModels() { + // signature: func (Writer).Write(p []byte) (n int, err error) + this.implements("io", "Writer", "Write") and + (inp.isParameter(0) and outp.isReceiver()) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } +} diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoIoutil.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoIoutil.go new file mode 100644 index 00000000000..6e7b87090ed --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoIoutil.go @@ -0,0 +1,45 @@ +// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT. + +package main + +import ( + "io" + "io/ioutil" +) + +func TaintStepTest_IoIoutilNopCloser_B0I0O0(sourceCQL interface{}) interface{} { + fromReader656 := sourceCQL.(io.Reader) + intoReadCloser414 := ioutil.NopCloser(fromReader656) + return intoReadCloser414 +} + +func TaintStepTest_IoIoutilReadAll_B0I0O0(sourceCQL interface{}) interface{} { + fromReader518 := sourceCQL.(io.Reader) + intoByte650, _ := ioutil.ReadAll(fromReader518) + return intoByte650 +} + +func TaintStepTest_IoWriterWrite_B0I0O0(sourceCQL interface{}) interface{} { + fromByte784 := sourceCQL.([]byte) + var intoWriter957 io.Writer + intoWriter957.Write(fromByte784) + return intoWriter957 +} + +func RunAllTaints_IoIoutil() { + { + source := newSource(0) + out := TaintStepTest_IoIoutilNopCloser_B0I0O0(source) + sink(0, out) + } + { + source := newSource(1) + out := TaintStepTest_IoIoutilReadAll_B0I0O0(source) + sink(1, out) + } + { + source := newSource(2) + out := TaintStepTest_IoWriterWrite_B0I0O0(source) + sink(2, out) + } +}