mirror of
https://github.com/github/codeql.git
synced 2026-01-29 14:23:03 +01:00
Move and extend Log module for package log with taint-tracking
This commit is contained in:
@@ -37,6 +37,7 @@ import semmle.go.frameworks.stdlib.NetHttp
|
||||
import semmle.go.frameworks.stdlib.NetHttpHttputil
|
||||
import semmle.go.frameworks.stdlib.NetMail
|
||||
import semmle.go.frameworks.stdlib.NetTextproto
|
||||
import semmle.go.frameworks.stdlib.Log
|
||||
import semmle.go.frameworks.stdlib.Path
|
||||
import semmle.go.frameworks.stdlib.PathFilepath
|
||||
import semmle.go.frameworks.stdlib.Reflect
|
||||
@@ -481,31 +482,67 @@ module URL {
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides models of commonly used functions in the `log` package. */
|
||||
module Log {
|
||||
private class LogCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
LogCall() {
|
||||
exists(string fn |
|
||||
fn.matches("Fatal%")
|
||||
or
|
||||
fn.matches("Panic%")
|
||||
or
|
||||
fn.matches("Print%")
|
||||
|
|
||||
this.getTarget().hasQualifiedName("log", fn)
|
||||
or
|
||||
this.getTarget().(Method).hasQualifiedName("log", "Logger", fn)
|
||||
/** Provides models of commonly used APIs in the `regexp` package. */
|
||||
module Regexp {
|
||||
private class Pattern extends RegexpPattern::Range, DataFlow::ArgumentNode {
|
||||
string fnName;
|
||||
|
||||
Pattern() {
|
||||
exists(Function fn | fnName.matches("Match%") or fnName.matches("%Compile%") |
|
||||
fn.hasQualifiedName("regexp", fnName) and
|
||||
this = fn.getACall().getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||
override DataFlow::Node getAParse() { result = this.getCall() }
|
||||
|
||||
override string getPattern() { result = this.asExpr().getStringValue() }
|
||||
|
||||
override DataFlow::Node getAUse() {
|
||||
fnName.matches("MustCompile%") and
|
||||
result = this.getCall().getASuccessor*()
|
||||
or
|
||||
fnName.matches("Compile%") and
|
||||
result = this.getCall().getResult(0).getASuccessor*()
|
||||
or
|
||||
result = this
|
||||
}
|
||||
}
|
||||
|
||||
/** A fatal log function, which calls `os.Exit`. */
|
||||
private class FatalLogFunction extends Function {
|
||||
FatalLogFunction() { exists(string fn | fn.matches("Fatal%") | hasQualifiedName("log", fn)) }
|
||||
private class MatchFunction extends RegexpMatchFunction::Range, Function {
|
||||
MatchFunction() {
|
||||
exists(string fn | fn.matches("Match%") | this.hasQualifiedName("regexp", fn))
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
override FunctionInput getRegexpArg() { result.isParameter(0) }
|
||||
|
||||
override FunctionInput getValue() { result.isParameter(1) }
|
||||
|
||||
override FunctionOutput getResult() { result.isResult(0) }
|
||||
}
|
||||
|
||||
private class MatchMethod extends RegexpMatchFunction::Range, Method {
|
||||
MatchMethod() {
|
||||
exists(string fn | fn.matches("Match%") | this.hasQualifiedName("regexp", "Regexp", fn))
|
||||
}
|
||||
|
||||
override FunctionInput getRegexpArg() { result.isReceiver() }
|
||||
|
||||
override FunctionInput getValue() { result.isParameter(0) }
|
||||
|
||||
override FunctionOutput getResult() { result.isResult() }
|
||||
}
|
||||
|
||||
private class ReplaceFunction extends RegexpReplaceFunction::Range, Method {
|
||||
ReplaceFunction() {
|
||||
exists(string fn | fn.matches("ReplaceAll%") | this.hasQualifiedName("regexp", "Regexp", fn))
|
||||
}
|
||||
|
||||
override FunctionInput getRegexpArg() { result.isReceiver() }
|
||||
|
||||
override FunctionInput getSource() { result.isParameter(0) }
|
||||
|
||||
override FunctionOutput getResult() { result.isResult() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
107
ql/src/semmle/go/frameworks/stdlib/Log.qll
Normal file
107
ql/src/semmle/go/frameworks/stdlib/Log.qll
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Provides classes modeling security-relevant aspects of the `log` package.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/** Provides models of commonly used functions in the `log` package. */
|
||||
module Log {
|
||||
private class LogCall extends LoggerCall::Range, DataFlow::CallNode {
|
||||
LogCall() {
|
||||
exists(string fn |
|
||||
fn.matches("Fatal%")
|
||||
or
|
||||
fn.matches("Panic%")
|
||||
or
|
||||
fn.matches("Print%")
|
||||
|
|
||||
this.getTarget().hasQualifiedName("log", fn)
|
||||
or
|
||||
this.getTarget().(Method).hasQualifiedName("log", "Logger", fn)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||
}
|
||||
|
||||
/** A fatal log function, which calls `os.Exit`. */
|
||||
private class FatalLogFunction extends Function {
|
||||
FatalLogFunction() { exists(string fn | fn.matches("Fatal%") | hasQualifiedName("log", fn)) }
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
||||
private class FunctionModels extends TaintTracking::FunctionModel {
|
||||
FunctionInput inp;
|
||||
FunctionOutput outp;
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func New(out io.Writer, prefix string, flag int) *Logger
|
||||
hasQualifiedName("log", "New") 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() {
|
||||
// signature: func (*Logger).Fatal(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatal") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Fatalf(format string, v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatalf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Fatalln(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Fatalln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Panic(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panic") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Panicf(format string, v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panicf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Panicln(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Panicln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Print(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Print") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Printf(format string, v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Printf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Println(v ...interface{})
|
||||
this.hasQualifiedName("log", "Logger", "Println") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).SetOutput(w io.Writer)
|
||||
this.hasQualifiedName("log", "Logger", "SetOutput") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Logger).SetPrefix(prefix string)
|
||||
this.hasQualifiedName("log", "Logger", "SetPrefix") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger).Writer() io.Writer
|
||||
this.hasQualifiedName("log", "Logger", "Writer") and
|
||||
(inp.isResult() and outp.isReceiver())
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input = inp and output = outp
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
func TaintStepTest_LogNew_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromLogger656 := sourceCQL.(*log.Logger)
|
||||
var intoWriter414 io.Writer
|
||||
intermediateCQL := log.New(intoWriter414, "", 0)
|
||||
link(fromLogger656, intermediateCQL)
|
||||
return intoWriter414
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatal_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface518 := sourceCQL.(interface{})
|
||||
var intoLogger650 log.Logger
|
||||
intoLogger650.Fatal(fromInterface518)
|
||||
return intoLogger650
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalf_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString784 := sourceCQL.(string)
|
||||
var intoLogger957 log.Logger
|
||||
intoLogger957.Fatalf(fromString784, nil)
|
||||
return intoLogger957
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalf_B0I1O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface520 := sourceCQL.(interface{})
|
||||
var intoLogger443 log.Logger
|
||||
intoLogger443.Fatalf("", fromInterface520)
|
||||
return intoLogger443
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerFatalln_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface127 := sourceCQL.(interface{})
|
||||
var intoLogger483 log.Logger
|
||||
intoLogger483.Fatalln(fromInterface127)
|
||||
return intoLogger483
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanic_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface989 := sourceCQL.(interface{})
|
||||
var intoLogger982 log.Logger
|
||||
intoLogger982.Panic(fromInterface989)
|
||||
return intoLogger982
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicf_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString417 := sourceCQL.(string)
|
||||
var intoLogger584 log.Logger
|
||||
intoLogger584.Panicf(fromString417, nil)
|
||||
return intoLogger584
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicf_B0I1O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface991 := sourceCQL.(interface{})
|
||||
var intoLogger881 log.Logger
|
||||
intoLogger881.Panicf("", fromInterface991)
|
||||
return intoLogger881
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPanicln_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface186 := sourceCQL.(interface{})
|
||||
var intoLogger284 log.Logger
|
||||
intoLogger284.Panicln(fromInterface186)
|
||||
return intoLogger284
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPrint_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface908 := sourceCQL.(interface{})
|
||||
var intoLogger137 log.Logger
|
||||
intoLogger137.Print(fromInterface908)
|
||||
return intoLogger137
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPrintf_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString494 := sourceCQL.(string)
|
||||
var intoLogger873 log.Logger
|
||||
intoLogger873.Printf(fromString494, nil)
|
||||
return intoLogger873
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPrintf_B0I1O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface599 := sourceCQL.(interface{})
|
||||
var intoLogger409 log.Logger
|
||||
intoLogger409.Printf("", fromInterface599)
|
||||
return intoLogger409
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerPrintln_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromInterface246 := sourceCQL.(interface{})
|
||||
var intoLogger898 log.Logger
|
||||
intoLogger898.Println(fromInterface246)
|
||||
return intoLogger898
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerSetOutput_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromLogger598 := sourceCQL.(log.Logger)
|
||||
var intoWriter631 io.Writer
|
||||
fromLogger598.SetOutput(intoWriter631)
|
||||
return intoWriter631
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerSetPrefix_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromString165 := sourceCQL.(string)
|
||||
var intoLogger150 log.Logger
|
||||
intoLogger150.SetPrefix(fromString165)
|
||||
return intoLogger150
|
||||
}
|
||||
|
||||
func TaintStepTest_LogLoggerWriter_B0I0O0(sourceCQL interface{}) interface{} {
|
||||
fromWriter340 := sourceCQL.(io.Writer)
|
||||
var intoLogger471 log.Logger
|
||||
intermediateCQL := intoLogger471.Writer()
|
||||
link(fromWriter340, intermediateCQL)
|
||||
return intoLogger471
|
||||
}
|
||||
|
||||
func RunAllTaints_Log() {
|
||||
{
|
||||
source := newSource(0)
|
||||
out := TaintStepTest_LogNew_B0I0O0(source)
|
||||
sink(0, out)
|
||||
}
|
||||
{
|
||||
source := newSource(1)
|
||||
out := TaintStepTest_LogLoggerFatal_B0I0O0(source)
|
||||
sink(1, out)
|
||||
}
|
||||
{
|
||||
source := newSource(2)
|
||||
out := TaintStepTest_LogLoggerFatalf_B0I0O0(source)
|
||||
sink(2, out)
|
||||
}
|
||||
{
|
||||
source := newSource(3)
|
||||
out := TaintStepTest_LogLoggerFatalf_B0I1O0(source)
|
||||
sink(3, out)
|
||||
}
|
||||
{
|
||||
source := newSource(4)
|
||||
out := TaintStepTest_LogLoggerFatalln_B0I0O0(source)
|
||||
sink(4, out)
|
||||
}
|
||||
{
|
||||
source := newSource(5)
|
||||
out := TaintStepTest_LogLoggerPanic_B0I0O0(source)
|
||||
sink(5, out)
|
||||
}
|
||||
{
|
||||
source := newSource(6)
|
||||
out := TaintStepTest_LogLoggerPanicf_B0I0O0(source)
|
||||
sink(6, out)
|
||||
}
|
||||
{
|
||||
source := newSource(7)
|
||||
out := TaintStepTest_LogLoggerPanicf_B0I1O0(source)
|
||||
sink(7, out)
|
||||
}
|
||||
{
|
||||
source := newSource(8)
|
||||
out := TaintStepTest_LogLoggerPanicln_B0I0O0(source)
|
||||
sink(8, out)
|
||||
}
|
||||
{
|
||||
source := newSource(9)
|
||||
out := TaintStepTest_LogLoggerPrint_B0I0O0(source)
|
||||
sink(9, out)
|
||||
}
|
||||
{
|
||||
source := newSource(10)
|
||||
out := TaintStepTest_LogLoggerPrintf_B0I0O0(source)
|
||||
sink(10, out)
|
||||
}
|
||||
{
|
||||
source := newSource(11)
|
||||
out := TaintStepTest_LogLoggerPrintf_B0I1O0(source)
|
||||
sink(11, out)
|
||||
}
|
||||
{
|
||||
source := newSource(12)
|
||||
out := TaintStepTest_LogLoggerPrintln_B0I0O0(source)
|
||||
sink(12, out)
|
||||
}
|
||||
{
|
||||
source := newSource(13)
|
||||
out := TaintStepTest_LogLoggerSetOutput_B0I0O0(source)
|
||||
sink(13, out)
|
||||
}
|
||||
{
|
||||
source := newSource(14)
|
||||
out := TaintStepTest_LogLoggerSetPrefix_B0I0O0(source)
|
||||
sink(14, out)
|
||||
}
|
||||
{
|
||||
source := newSource(15)
|
||||
out := TaintStepTest_LogLoggerWriter_B0I0O0(source)
|
||||
sink(15, out)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user