зеркало из https://github.com/github/codeql-go.git
Merge pull request #251 from gagliardetto/standard-lib-pt-1
Add taint-tracking for archive/tar and archive/zip
This commit is contained in:
Коммит
e9ae697d0d
|
@ -3,6 +3,8 @@
|
|||
*/
|
||||
|
||||
import go
|
||||
import semmle.go.frameworks.stdlib.ArchiveTar
|
||||
import semmle.go.frameworks.stdlib.ArchiveZip
|
||||
|
||||
/** A `String()` method. */
|
||||
class StringMethod extends TaintTracking::FunctionModel, Method {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `archive/tar` package.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/** Provides models of commonly used functions in the `archive/tar` package. */
|
||||
module ArchiveTar {
|
||||
private class FunctionModels extends TaintTracking::FunctionModel {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
FunctionModels() {
|
||||
// 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 MethodModels extends TaintTracking::FunctionModel, Method {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
MethodModels() {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `archive/zip` package.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/** Provides models of commonly used functions in the `archive/zip` package. */
|
||||
module ArchiveZip {
|
||||
private class FunctionModels extends TaintTracking::FunctionModel {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
FunctionModels() {
|
||||
// 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 MethodModels extends TaintTracking::FunctionModel, Method {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
MethodModels() {
|
||||
// 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 (*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.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input = inp and output = outp
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromFileInfo656 := sourceCQL.(os.FileInfo)
|
||||
intoHeader414, _ := tar.FileInfoHeader(fromFileInfo656, "")
|
||||
return intoHeader414
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarNewReader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromReader518 := sourceCQL.(io.Reader)
|
||||
intoReader650 := tar.NewReader(fromReader518)
|
||||
return intoReader650
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarNewWriter_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromWriter784 := sourceCQL.(*tar.Writer)
|
||||
var intoWriter957 io.Writer
|
||||
intermediateCQL := tar.NewWriter(intoWriter957)
|
||||
link(fromWriter784, intermediateCQL)
|
||||
return intoWriter957
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromHeader520 := sourceCQL.(tar.Header)
|
||||
intoFileInfo443 := fromHeader520.FileInfo()
|
||||
return intoFileInfo443
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarReaderNext_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromReader127 := sourceCQL.(tar.Reader)
|
||||
intoHeader483, _ := fromReader127.Next()
|
||||
return intoHeader483
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarReaderRead_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromReader989 := sourceCQL.(tar.Reader)
|
||||
var intoByte982 []byte
|
||||
fromReader989.Read(intoByte982)
|
||||
return intoByte982
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarWriterWrite_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromByte417 := sourceCQL.([]byte)
|
||||
var intoWriter584 tar.Writer
|
||||
intoWriter584.Write(fromByte417)
|
||||
return intoWriter584
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromHeader991 := sourceCQL.(*tar.Header)
|
||||
var intoWriter881 tar.Writer
|
||||
intoWriter881.WriteHeader(fromHeader991)
|
||||
return intoWriter881
|
||||
}
|
||||
|
||||
func RunAllTaints_ArchiveTar() {
|
||||
{
|
||||
source := newSource(0)
|
||||
out := TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(source)
|
||||
sink(0, out)
|
||||
}
|
||||
{
|
||||
source := newSource(1)
|
||||
out := TaintStepTest_ArchiveTarNewReader_B0I0O0(source)
|
||||
sink(1, out)
|
||||
}
|
||||
{
|
||||
source := newSource(2)
|
||||
out := TaintStepTest_ArchiveTarNewWriter_B0I0O0(source)
|
||||
sink(2, out)
|
||||
}
|
||||
{
|
||||
source := newSource(3)
|
||||
out := TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(source)
|
||||
sink(3, out)
|
||||
}
|
||||
{
|
||||
source := newSource(4)
|
||||
out := TaintStepTest_ArchiveTarReaderNext_B0I0O0(source)
|
||||
sink(4, out)
|
||||
}
|
||||
{
|
||||
source := newSource(5)
|
||||
out := TaintStepTest_ArchiveTarReaderRead_B0I0O0(source)
|
||||
sink(5, out)
|
||||
}
|
||||
{
|
||||
source := newSource(6)
|
||||
out := TaintStepTest_ArchiveTarWriterWrite_B0I0O0(source)
|
||||
sink(6, out)
|
||||
}
|
||||
{
|
||||
source := newSource(7)
|
||||
out := TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(source)
|
||||
sink(7, out)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromFileInfo656 := sourceCQL.(os.FileInfo)
|
||||
intoFileHeader414, _ := zip.FileInfoHeader(fromFileInfo656)
|
||||
return intoFileHeader414
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipNewReader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromReaderAt518 := sourceCQL.(io.ReaderAt)
|
||||
intoReader650, _ := zip.NewReader(fromReaderAt518, 0)
|
||||
return intoReader650
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipNewWriter_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromWriter784 := sourceCQL.(*zip.Writer)
|
||||
var intoWriter957 io.Writer
|
||||
intermediateCQL := zip.NewWriter(intoWriter957)
|
||||
link(fromWriter784, intermediateCQL)
|
||||
return intoWriter957
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipOpenReader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString520 := sourceCQL.(string)
|
||||
intoReadCloser443, _ := zip.OpenReader(fromString520)
|
||||
return intoReadCloser443
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipFileOpen_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromFile127 := sourceCQL.(zip.File)
|
||||
intoReadCloser483, _ := fromFile127.Open()
|
||||
return intoReadCloser483
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipWriterCreate_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromWriter989 := sourceCQL.(io.Writer)
|
||||
var intoWriter982 zip.Writer
|
||||
intermediateCQL, _ := intoWriter982.Create("")
|
||||
link(fromWriter989, intermediateCQL)
|
||||
return intoWriter982
|
||||
}
|
||||
|
||||
func TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromWriter417 := sourceCQL.(io.Writer)
|
||||
var intoWriter584 zip.Writer
|
||||
intermediateCQL, _ := intoWriter584.CreateHeader(nil)
|
||||
link(fromWriter417, intermediateCQL)
|
||||
return intoWriter584
|
||||
}
|
||||
|
||||
func RunAllTaints_ArchiveZip() {
|
||||
{
|
||||
source := newSource(0)
|
||||
out := TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(source)
|
||||
sink(0, out)
|
||||
}
|
||||
{
|
||||
source := newSource(1)
|
||||
out := TaintStepTest_ArchiveZipNewReader_B0I0O0(source)
|
||||
sink(1, out)
|
||||
}
|
||||
{
|
||||
source := newSource(2)
|
||||
out := TaintStepTest_ArchiveZipNewWriter_B0I0O0(source)
|
||||
sink(2, out)
|
||||
}
|
||||
{
|
||||
source := newSource(3)
|
||||
out := TaintStepTest_ArchiveZipOpenReader_B0I0O0(source)
|
||||
sink(3, out)
|
||||
}
|
||||
{
|
||||
source := newSource(4)
|
||||
out := TaintStepTest_ArchiveZipFileOpen_B0I0O0(source)
|
||||
sink(4, out)
|
||||
}
|
||||
{
|
||||
source := newSource(5)
|
||||
out := TaintStepTest_ArchiveZipWriterCreate_B0I0O0(source)
|
||||
sink(5, out)
|
||||
}
|
||||
{
|
||||
source := newSource(6)
|
||||
out := TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(source)
|
||||
sink(6, out)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @kind problem
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/* A special helper function used inside the test code */
|
||||
class Link extends TaintTracking::FunctionModel {
|
||||
Link() { hasQualifiedName(_, "link") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
inp.isParameter(0) and outp.isParameter(1)
|
||||
}
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node source, DataFlow::CallNode call) {
|
||||
exists(Function fn | fn.hasQualifiedName(_, "newSource") |
|
||||
call = fn.getACall() and source = call.getResult()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, DataFlow::CallNode call) {
|
||||
exists(Function fn | fn.hasQualifiedName(_, "sink") |
|
||||
call = fn.getACall() and sink = call.getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
class FlowConf extends TaintTracking::Configuration {
|
||||
FlowConf() { this = "FlowConf" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isSource(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the result of the provided sourceCall flows to the corresponding sink,
|
||||
* both marked by the same numeric first argument.
|
||||
*/
|
||||
predicate flowsToSink(DataFlow::CallNode sourceCall) {
|
||||
exists(
|
||||
FlowConf cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::CallNode sinkCall
|
||||
|
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
(
|
||||
isSource(source.getNode(), sourceCall) and
|
||||
isSink(sink.getNode(), sinkCall) and
|
||||
sourceCall.getArgument(0).getIntValue() = sinkCall.getArgument(0).getIntValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/* Show only flow sources that DON'T flow to their dedicated sink. */
|
||||
from DataFlow::CallNode sourceCall
|
||||
where isSource(_, sourceCall) and not flowsToSink(sourceCall)
|
||||
select sourceCall, "No flow to its sink"
|
|
@ -0,0 +1,10 @@
|
|||
package main
|
||||
|
||||
func main() {}
|
||||
func sink(id int, v interface{}) {}
|
||||
|
||||
func link(from interface{}, into interface{}) {}
|
||||
|
||||
func newSource(id int) interface{} {
|
||||
return nil
|
||||
}
|
Загрузка…
Ссылка в новой задаче