diff --git a/ql/src/semmle/go/frameworks/Stdlib.qll b/ql/src/semmle/go/frameworks/Stdlib.qll index 8c4ef5b9017..92e41cb36f6 100644 --- a/ql/src/semmle/go/frameworks/Stdlib.qll +++ b/ql/src/semmle/go/frameworks/Stdlib.qll @@ -3,6 +3,7 @@ */ import go +import semmle.go.frameworks.stdlib.ImportAll /** A `String()` method. */ class StringMethod extends TaintTracking::FunctionModel, Method { diff --git a/ql/src/semmle/go/frameworks/stdlib/ArchiveTarTaintTracking.qll b/ql/src/semmle/go/frameworks/stdlib/ArchiveTarTaintTracking.qll new file mode 100644 index 00000000000..4f0202900d0 --- /dev/null +++ b/ql/src/semmle/go/frameworks/stdlib/ArchiveTarTaintTracking.qll @@ -0,0 +1,63 @@ +/** + * Provides classes modeling security-relevant aspects of the standard libraries. + */ + +import go + +/** Provides models of commonly used functions in the `archive/tar` package. */ +module ArchiveTarTaintTracking { + private class FunctionTaintTracking extends TaintTracking::FunctionModel { + FunctionInput inp; + FunctionOutput outp; + + FunctionTaintTracking() { + // signature: func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) + hasQualifiedName("archive/tar", "FileInfoHeader") and + (inp.isParameter(0) and outp.isResult(0)) + or + // signature: func NewReader(r io.Reader) *Reader + hasQualifiedName("archive/tar", "NewReader") and + (inp.isParameter(0) and outp.isResult()) + or + // signature: func NewWriter(w io.Writer) *Writer + hasQualifiedName("archive/tar", "NewWriter") and + (inp.isResult() and outp.isParameter(0)) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } + + private class MethodAndInterfaceTaintTracking extends TaintTracking::FunctionModel, Method { + FunctionInput inp; + FunctionOutput outp; + + MethodAndInterfaceTaintTracking() { + // Methods: + // signature: func (*Header).FileInfo() os.FileInfo + this.(Method).hasQualifiedName("archive/tar", "Header", "FileInfo") and + (inp.isReceiver() and outp.isResult()) + or + // signature: func (*Reader).Next() (*Header, error) + this.(Method).hasQualifiedName("archive/tar", "Reader", "Next") and + (inp.isReceiver() and outp.isResult(0)) + or + // signature: func (*Reader).Read(b []byte) (int, error) + this.(Method).hasQualifiedName("archive/tar", "Reader", "Read") and + (inp.isReceiver() and outp.isParameter(0)) + or + // signature: func (*Writer).Write(b []byte) (int, error) + this.(Method).hasQualifiedName("archive/tar", "Writer", "Write") and + (inp.isParameter(0) and outp.isReceiver()) + or + // signature: func (*Writer).WriteHeader(hdr *Header) error + this.(Method).hasQualifiedName("archive/tar", "Writer", "WriteHeader") and + (inp.isParameter(0) and outp.isReceiver()) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } +} diff --git a/ql/src/semmle/go/frameworks/stdlib/ArchiveZipTaintTracking.qll b/ql/src/semmle/go/frameworks/stdlib/ArchiveZipTaintTracking.qll new file mode 100644 index 00000000000..9ef1b1a050d --- /dev/null +++ b/ql/src/semmle/go/frameworks/stdlib/ArchiveZipTaintTracking.qll @@ -0,0 +1,86 @@ +/** + * Provides classes modeling security-relevant aspects of the standard libraries. + */ + +import go + +/** Provides models of commonly used functions in the `archive/zip` package. */ +module ArchiveZipTaintTracking { + private class FunctionTaintTracking extends TaintTracking::FunctionModel { + FunctionInput inp; + FunctionOutput outp; + + FunctionTaintTracking() { + // signature: func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) + hasQualifiedName("archive/zip", "FileInfoHeader") and + (inp.isParameter(0) and outp.isResult(0)) + or + // signature: func NewReader(r io.ReaderAt, size int64) (*Reader, error) + hasQualifiedName("archive/zip", "NewReader") and + (inp.isParameter(0) and outp.isResult(0)) + or + // signature: func NewWriter(w io.Writer) *Writer + hasQualifiedName("archive/zip", "NewWriter") and + (inp.isResult() and outp.isParameter(0)) + or + // signature: func OpenReader(name string) (*ReadCloser, error) + hasQualifiedName("archive/zip", "OpenReader") and + (inp.isParameter(0) and outp.isResult(0)) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } + + private class MethodAndInterfaceTaintTracking extends TaintTracking::FunctionModel, Method { + FunctionInput inp; + FunctionOutput outp; + + MethodAndInterfaceTaintTracking() { + // Methods: + // signature: func (*File).Open() (io.ReadCloser, error) + this.(Method).hasQualifiedName("archive/zip", "File", "Open") and + (inp.isReceiver() and outp.isResult(0)) + or + // signature: func (*FileHeader).FileInfo() os.FileInfo + this.(Method).hasQualifiedName("archive/zip", "FileHeader", "FileInfo") and + (inp.isReceiver() and outp.isResult()) + or + // signature: func (*FileHeader).Mode() (mode os.FileMode) + this.(Method).hasQualifiedName("archive/zip", "FileHeader", "Mode") and + (inp.isReceiver() and outp.isResult()) + or + // signature: func (*FileHeader).SetMode(mode os.FileMode) + this.(Method).hasQualifiedName("archive/zip", "FileHeader", "SetMode") and + (inp.isParameter(0) and outp.isReceiver()) + or + // signature: func (*Reader).RegisterDecompressor(method uint16, dcomp Decompressor) + this.(Method).hasQualifiedName("archive/zip", "Reader", "RegisterDecompressor") and + (inp.isParameter(1) and outp.isReceiver()) + or + // signature: func (*Writer).Create(name string) (io.Writer, error) + this.(Method).hasQualifiedName("archive/zip", "Writer", "Create") and + (inp.isResult(0) and outp.isReceiver()) + or + // signature: func (*Writer).CreateHeader(fh *FileHeader) (io.Writer, error) + this.(Method).hasQualifiedName("archive/zip", "Writer", "CreateHeader") and + ( + (inp.isParameter(0) or inp.isResult(0)) and + outp.isReceiver() + ) + or + // signature: func (*Writer).RegisterCompressor(method uint16, comp Compressor) + this.(Method).hasQualifiedName("archive/zip", "Writer", "RegisterCompressor") and + (inp.isParameter(1) and outp.isReceiver()) + or + // signature: func (*Writer).SetComment(comment string) error + this.(Method).hasQualifiedName("archive/zip", "Writer", "SetComment") and + (inp.isParameter(0) and outp.isReceiver()) + } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + input = inp and output = outp + } + } +} diff --git a/ql/src/semmle/go/frameworks/stdlib/ImportAll.qll b/ql/src/semmle/go/frameworks/stdlib/ImportAll.qll new file mode 100644 index 00000000000..0021de83c3a --- /dev/null +++ b/ql/src/semmle/go/frameworks/stdlib/ImportAll.qll @@ -0,0 +1,7 @@ +/** + * Provides imports of all the standard libraries. + */ + +import go +import semmle.go.frameworks.stdlib.ArchiveTarTaintTracking +import semmle.go.frameworks.stdlib.ArchiveZipTaintTracking diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveTarTaintTracking.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveTarTaintTracking.go new file mode 100644 index 00000000000..fa1ac89c84f --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveTarTaintTracking.go @@ -0,0 +1,210 @@ +// WARNING: This file was automatically generated. DO NOT EDIT. + +package main + +import ( + "archive/tar" + "io" + "os" +) + +func TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileInfo656` into `intoHeader414`. + + // Assume that `sourceCQL` has the underlying type of `fromFileInfo656`: + fromFileInfo656 := sourceCQL.(os.FileInfo) + + // Call the function that transfers the taint + // from the parameter `fromFileInfo656` to result `intoHeader414` + // (`intoHeader414` is now tainted). + intoHeader414, _ := tar.FileInfoHeader(fromFileInfo656, "") + + // Return the tainted `intoHeader414`: + return intoHeader414 +} + +func TaintStepTest_ArchiveTarNewReader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromReader518` into `intoReader650`. + + // Assume that `sourceCQL` has the underlying type of `fromReader518`: + fromReader518 := sourceCQL.(io.Reader) + + // Call the function that transfers the taint + // from the parameter `fromReader518` to result `intoReader650` + // (`intoReader650` is now tainted). + intoReader650 := tar.NewReader(fromReader518) + + // Return the tainted `intoReader650`: + return intoReader650 +} + +func TaintStepTest_ArchiveTarNewWriter_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromWriter784` into `intoWriter957`. + + // Assume that `sourceCQL` has the underlying type of `fromWriter784`: + fromWriter784 := sourceCQL.(*tar.Writer) + + // Declare `intoWriter957` variable: + var intoWriter957 io.Writer + + // Call the function that will transfer the taint + // from the result `intermediateCQL` to parameter `intoWriter957`: + intermediateCQL := tar.NewWriter(intoWriter957) + + // Extra step (`fromWriter784` taints `intermediateCQL`, which taints `intoWriter957`: + link(fromWriter784, intermediateCQL) + + // Return the tainted `intoWriter957`: + return intoWriter957 +} + +func TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromHeader520` into `intoFileInfo443`. + + // Assume that `sourceCQL` has the underlying type of `fromHeader520`: + fromHeader520 := sourceCQL.(tar.Header) + + // Call the method that transfers the taint + // from the receiver `fromHeader520` to the result `intoFileInfo443` + // (`intoFileInfo443` is now tainted). + intoFileInfo443 := fromHeader520.FileInfo() + + // Return the tainted `intoFileInfo443`: + return intoFileInfo443 +} + +func TaintStepTest_ArchiveTarReaderNext_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromReader127` into `intoHeader483`. + + // Assume that `sourceCQL` has the underlying type of `fromReader127`: + fromReader127 := sourceCQL.(tar.Reader) + + // Call the method that transfers the taint + // from the receiver `fromReader127` to the result `intoHeader483` + // (`intoHeader483` is now tainted). + intoHeader483, _ := fromReader127.Next() + + // Return the tainted `intoHeader483`: + return intoHeader483 +} + +func TaintStepTest_ArchiveTarReaderRead_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromReader989` into `intoByte982`. + + // Assume that `sourceCQL` has the underlying type of `fromReader989`: + fromReader989 := sourceCQL.(tar.Reader) + + // Declare `intoByte982` variable: + var intoByte982 []byte + + // Call the method that transfers the taint + // from the receiver `fromReader989` to the argument `intoByte982` + // (`intoByte982` is now tainted). + fromReader989.Read(intoByte982) + + // Return the tainted `intoByte982`: + return intoByte982 +} + +func TaintStepTest_ArchiveTarWriterWrite_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromByte417` into `intoWriter584`. + + // Assume that `sourceCQL` has the underlying type of `fromByte417`: + fromByte417 := sourceCQL.([]byte) + + // Declare `intoWriter584` variable: + var intoWriter584 tar.Writer + + // Call the method that transfers the taint + // from the parameter `fromByte417` to the receiver `intoWriter584` + // (`intoWriter584` is now tainted). + intoWriter584.Write(fromByte417) + + // Return the tainted `intoWriter584`: + return intoWriter584 +} + +func TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromHeader991` into `intoWriter881`. + + // Assume that `sourceCQL` has the underlying type of `fromHeader991`: + fromHeader991 := sourceCQL.(*tar.Header) + + // Declare `intoWriter881` variable: + var intoWriter881 tar.Writer + + // Call the method that transfers the taint + // from the parameter `fromHeader991` to the receiver `intoWriter881` + // (`intoWriter881` is now tainted). + intoWriter881.WriteHeader(fromHeader991) + + // Return the tainted `intoWriter881`: + return intoWriter881 +} + +func RunAllTaints_ArchiveTar() { + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarNewReader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarNewWriter_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarReaderNext_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarReaderRead_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarWriterWrite_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } +} diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZipTaintTracking.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZipTaintTracking.go new file mode 100644 index 00000000000..00655690d71 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZipTaintTracking.go @@ -0,0 +1,364 @@ +// WARNING: This file was automatically generated. DO NOT EDIT. + +package main + +import ( + "archive/zip" + "io" + "os" +) + +func TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileInfo656` into `intoFileHeader414`. + + // Assume that `sourceCQL` has the underlying type of `fromFileInfo656`: + fromFileInfo656 := sourceCQL.(os.FileInfo) + + // Call the function that transfers the taint + // from the parameter `fromFileInfo656` to result `intoFileHeader414` + // (`intoFileHeader414` is now tainted). + intoFileHeader414, _ := zip.FileInfoHeader(fromFileInfo656) + + // Return the tainted `intoFileHeader414`: + return intoFileHeader414 +} + +func TaintStepTest_ArchiveZipNewReader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromReaderAt518` into `intoReader650`. + + // Assume that `sourceCQL` has the underlying type of `fromReaderAt518`: + fromReaderAt518 := sourceCQL.(io.ReaderAt) + + // Call the function that transfers the taint + // from the parameter `fromReaderAt518` to result `intoReader650` + // (`intoReader650` is now tainted). + intoReader650, _ := zip.NewReader(fromReaderAt518, 0) + + // Return the tainted `intoReader650`: + return intoReader650 +} + +func TaintStepTest_ArchiveZipNewWriter_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromWriter784` into `intoWriter957`. + + // Assume that `sourceCQL` has the underlying type of `fromWriter784`: + fromWriter784 := sourceCQL.(*zip.Writer) + + // Declare `intoWriter957` variable: + var intoWriter957 io.Writer + + // Call the function that will transfer the taint + // from the result `intermediateCQL` to parameter `intoWriter957`: + intermediateCQL := zip.NewWriter(intoWriter957) + + // Extra step (`fromWriter784` taints `intermediateCQL`, which taints `intoWriter957`: + link(fromWriter784, intermediateCQL) + + // Return the tainted `intoWriter957`: + return intoWriter957 +} + +func TaintStepTest_ArchiveZipOpenReader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromString520` into `intoReadCloser443`. + + // Assume that `sourceCQL` has the underlying type of `fromString520`: + fromString520 := sourceCQL.(string) + + // Call the function that transfers the taint + // from the parameter `fromString520` to result `intoReadCloser443` + // (`intoReadCloser443` is now tainted). + intoReadCloser443, _ := zip.OpenReader(fromString520) + + // Return the tainted `intoReadCloser443`: + return intoReadCloser443 +} + +func TaintStepTest_ArchiveZipFileOpen_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFile127` into `intoReadCloser483`. + + // Assume that `sourceCQL` has the underlying type of `fromFile127`: + fromFile127 := sourceCQL.(zip.File) + + // Call the method that transfers the taint + // from the receiver `fromFile127` to the result `intoReadCloser483` + // (`intoReadCloser483` is now tainted). + intoReadCloser483, _ := fromFile127.Open() + + // Return the tainted `intoReadCloser483`: + return intoReadCloser483 +} + +func TaintStepTest_ArchiveZipFileHeaderFileInfo_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileHeader989` into `intoFileInfo982`. + + // Assume that `sourceCQL` has the underlying type of `fromFileHeader989`: + fromFileHeader989 := sourceCQL.(zip.FileHeader) + + // Call the method that transfers the taint + // from the receiver `fromFileHeader989` to the result `intoFileInfo982` + // (`intoFileInfo982` is now tainted). + intoFileInfo982 := fromFileHeader989.FileInfo() + + // Return the tainted `intoFileInfo982`: + return intoFileInfo982 +} + +func TaintStepTest_ArchiveZipFileHeaderMode_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileHeader417` into `intoFileMode584`. + + // Assume that `sourceCQL` has the underlying type of `fromFileHeader417`: + fromFileHeader417 := sourceCQL.(zip.FileHeader) + + // Call the method that transfers the taint + // from the receiver `fromFileHeader417` to the result `intoFileMode584` + // (`intoFileMode584` is now tainted). + intoFileMode584 := fromFileHeader417.Mode() + + // Return the tainted `intoFileMode584`: + return intoFileMode584 +} + +func TaintStepTest_ArchiveZipFileHeaderSetMode_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileMode991` into `intoFileHeader881`. + + // Assume that `sourceCQL` has the underlying type of `fromFileMode991`: + fromFileMode991 := sourceCQL.(os.FileMode) + + // Declare `intoFileHeader881` variable: + var intoFileHeader881 zip.FileHeader + + // Call the method that transfers the taint + // from the parameter `fromFileMode991` to the receiver `intoFileHeader881` + // (`intoFileHeader881` is now tainted). + intoFileHeader881.SetMode(fromFileMode991) + + // Return the tainted `intoFileHeader881`: + return intoFileHeader881 +} + +func TaintStepTest_ArchiveZipReaderRegisterDecompressor_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromDecompressor186` into `intoReader284`. + + // Assume that `sourceCQL` has the underlying type of `fromDecompressor186`: + fromDecompressor186 := sourceCQL.(zip.Decompressor) + + // Declare `intoReader284` variable: + var intoReader284 zip.Reader + + // Call the method that transfers the taint + // from the parameter `fromDecompressor186` to the receiver `intoReader284` + // (`intoReader284` is now tainted). + intoReader284.RegisterDecompressor(0, fromDecompressor186) + + // Return the tainted `intoReader284`: + return intoReader284 +} + +func TaintStepTest_ArchiveZipWriterCreate_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromWriter908` into `intoWriter137`. + + // Assume that `sourceCQL` has the underlying type of `fromWriter908`: + fromWriter908 := sourceCQL.(io.Writer) + + // Declare `intoWriter137` variable: + var intoWriter137 zip.Writer + + // Call the method that will transfer the taint + // from the result `intermediateCQL` to receiver `intoWriter137`: + intermediateCQL, _ := intoWriter137.Create("") + + // Extra step (`fromWriter908` taints `intermediateCQL`, which taints `intoWriter137`: + link(fromWriter908, intermediateCQL) + + // Return the tainted `intoWriter137`: + return intoWriter137 +} + +func TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromFileHeader494` into `intoWriter873`. + + // Assume that `sourceCQL` has the underlying type of `fromFileHeader494`: + fromFileHeader494 := sourceCQL.(*zip.FileHeader) + + // Declare `intoWriter873` variable: + var intoWriter873 zip.Writer + + // Call the method that transfers the taint + // from the parameter `fromFileHeader494` to the receiver `intoWriter873` + // (`intoWriter873` is now tainted). + intoWriter873.CreateHeader(fromFileHeader494) + + // Return the tainted `intoWriter873`: + return intoWriter873 +} + +func TaintStepTest_ArchiveZipWriterCreateHeader_B0I1O0(sourceCQL interface{}) interface{} { + // The flow is from `fromWriter599` into `intoWriter409`. + + // Assume that `sourceCQL` has the underlying type of `fromWriter599`: + fromWriter599 := sourceCQL.(io.Writer) + + // Declare `intoWriter409` variable: + var intoWriter409 zip.Writer + + // Call the method that will transfer the taint + // from the result `intermediateCQL` to receiver `intoWriter409`: + intermediateCQL, _ := intoWriter409.CreateHeader(nil) + + // Extra step (`fromWriter599` taints `intermediateCQL`, which taints `intoWriter409`: + link(fromWriter599, intermediateCQL) + + // Return the tainted `intoWriter409`: + return intoWriter409 +} + +func TaintStepTest_ArchiveZipWriterRegisterCompressor_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromCompressor246` into `intoWriter898`. + + // Assume that `sourceCQL` has the underlying type of `fromCompressor246`: + fromCompressor246 := sourceCQL.(zip.Compressor) + + // Declare `intoWriter898` variable: + var intoWriter898 zip.Writer + + // Call the method that transfers the taint + // from the parameter `fromCompressor246` to the receiver `intoWriter898` + // (`intoWriter898` is now tainted). + intoWriter898.RegisterCompressor(0, fromCompressor246) + + // Return the tainted `intoWriter898`: + return intoWriter898 +} + +func TaintStepTest_ArchiveZipWriterSetComment_B0I0O0(sourceCQL interface{}) interface{} { + // The flow is from `fromString598` into `intoWriter631`. + + // Assume that `sourceCQL` has the underlying type of `fromString598`: + fromString598 := sourceCQL.(string) + + // Declare `intoWriter631` variable: + var intoWriter631 zip.Writer + + // Call the method that transfers the taint + // from the parameter `fromString598` to the receiver `intoWriter631` + // (`intoWriter631` is now tainted). + intoWriter631.SetComment(fromString598) + + // Return the tainted `intoWriter631`: + return intoWriter631 +} + +func RunAllTaints_ArchiveZip() { + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipNewReader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipNewWriter_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipOpenReader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipFileOpen_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipFileHeaderFileInfo_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipFileHeaderMode_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipFileHeaderSetMode_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipReaderRegisterDecompressor_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipWriterCreate_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipWriterCreateHeader_B0I1O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipWriterRegisterCompressor_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } + { + // Create a new source: + source := newSource() + // Run the taint scenario: + out := TaintStepTest_ArchiveZipWriterSetComment_B0I0O0(source) + // If the taint step(s) succeeded, then `out` is tainted and will be sink-able here: + sink(out) + } +} diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/StdlibTaintFlow.expected b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/StdlibTaintFlow.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/StdlibTaintFlow.ql b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/StdlibTaintFlow.ql new file mode 100644 index 00000000000..b3f33bce9d4 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/StdlibTaintFlow.ql @@ -0,0 +1,38 @@ +/** + * @kind path-problem + */ + +import go +import DataFlow::PathGraph + +class Source extends DataFlow::ExprNode { + Source() { + exists(Function fn | fn.hasQualifiedName(_, "newSource") | this = fn.getACall().getResult()) + } +} + +class Sink extends DataFlow::ExprNode { + Sink() { + exists(Function fn | fn.hasQualifiedName(_, "sink") | this = fn.getACall().getArgument(0)) + } +} + +class Link extends TaintTracking::FunctionModel { + Link() { hasQualifiedName(_, "link") } + + override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) { + inp.isParameter(0) and outp.isParameter(1) + } +} + +class FlowConf extends TaintTracking::Configuration { + FlowConf() { this = "FlowConf" } + + override predicate isSource(DataFlow::Node source) { source instanceof Source } + + override predicate isSink(DataFlow::Node sink) { sink instanceof Sink } +} + +from FlowConf cfg, DataFlow::PathNode source, DataFlow::PathNode sink +where cfg.hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Flow from $@.", source.getNode(), "source" diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/main.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/main.go new file mode 100644 index 00000000000..197f9809576 --- /dev/null +++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/main.go @@ -0,0 +1,10 @@ +package main + +func main() {} +func sink(v interface{}) {} + +func link(from interface{}, into interface{}) {} + +func newSource() interface{} { + return nil +}