Skip to content

Commit 8d099cb

Browse files
committed
Recognize more non-returning logging functions
1 parent 9618e9b commit 8d099cb

4 files changed

Lines changed: 36 additions & 15 deletions

File tree

go/ql/lib/semmle/go/Concepts.qll

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -413,17 +413,13 @@ private class ExternalLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
413413
}
414414
}
415415

416-
/**
417-
* A call to an interface that looks like a logger. It is common to use a
418-
* locally-defined interface for logging to make it easy to changing logging
419-
* library.
420-
*/
421-
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
422-
HeuristicLoggerCall() {
423-
exists(Method m, string tp, string logFunctionPrefix, string name |
424-
m = this.getTarget() and
425-
m.hasQualifiedName(_, tp, name) and
426-
m.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
416+
private class HeuristicLoggerFunction extends Method {
417+
string logFunctionPrefix;
418+
419+
HeuristicLoggerFunction() {
420+
exists(string tp, string name |
421+
this.hasQualifiedName(_, tp, name) and
422+
this.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
427423
|
428424
tp.regexpMatch(".*[lL]ogger") and
429425
logFunctionPrefix =
@@ -435,6 +431,19 @@ private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode
435431
)
436432
}
437433

434+
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
435+
436+
override predicate mustPanic() { logFunctionPrefix = "Panic" }
437+
}
438+
439+
/**
440+
* A call to an interface that looks like a logger. It is common to use a
441+
* locally-defined interface for logging to make it easy to changing logging
442+
* library.
443+
*/
444+
private class HeuristicLoggerCall extends LoggerCall::Range, DataFlow::CallNode {
445+
HeuristicLoggerCall() { this.getTarget() instanceof HeuristicLoggerFunction }
446+
438447
override DataFlow::Node getAMessageComponent() { result = this.getASyntacticArgument() }
439448
}
440449

go/ql/lib/semmle/go/frameworks/Logrus.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ module Logrus {
2828
this.(Method).hasQualifiedName(packagePath(), ["Entry", "Logger"], name)
2929
)
3030
}
31+
32+
override predicate mayReturnNormally() {
33+
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
34+
this.getName() = level + suffix
35+
)
36+
}
3137
}
3238

3339
private class StringFormatters extends StringOps::Formatting::Range instanceof LogFunction {

go/ql/lib/semmle/go/frameworks/Zap.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ module Zap {
4747
}
4848

4949
/** A Zap logging function which always panics. */
50-
private class FatalLogMethod extends Method {
50+
private class FatalLogMethod extends ZapFunction {
5151
FatalLogMethod() {
5252
this.hasQualifiedName(packagePath(), "Logger", "Fatal")
5353
or
@@ -58,7 +58,7 @@ module Zap {
5858
}
5959

6060
/** A Zap logging function which always panics. */
61-
private class MustPanicLogMethod extends Method {
61+
private class MustPanicLogMethod extends ZapFunction {
6262
MustPanicLogMethod() {
6363
this.hasQualifiedName(packagePath(), "Logger", "Panic")
6464
or

go/ql/lib/semmle/go/frameworks/stdlib/Log.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,20 @@ module Log {
2929
}
3030

3131
private class LogFormatter extends StringOps::Formatting::Range instanceof LogFunction {
32-
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf"] }
32+
LogFormatter() { this.getName() = ["Fatalf", "Panicf", "Printf", "Panic", "Panicf", "Panicln"] }
3333

3434
override int getFormatStringIndex() { result = 0 }
3535
}
3636

3737
/** A fatal log function, which calls `os.Exit`. */
3838
private class FatalLogFunction extends Function {
39-
FatalLogFunction() { this.hasQualifiedName("log", ["Fatal", "Fatalf", "Fatalln"]) }
39+
FatalLogFunction() {
40+
exists(string fn | fn = ["Fatal", "Fatalf", "Fatalln"] |
41+
this.hasQualifiedName("log", fn)
42+
or
43+
this.(Method).hasQualifiedName("log", "Logger", fn)
44+
)
45+
}
4046

4147
override predicate mayReturnNormally() { none() }
4248
}

0 commit comments

Comments
 (0)