Python: Add Logging concept

This commit is contained in:
Rasmus Wriedt Larsen
2021-06-25 13:54:56 +02:00
parent a7eb1b3a12
commit 36c9ceb13b
3 changed files with 91 additions and 0 deletions

View File

@@ -268,6 +268,35 @@ private class EncodingAdditionalTaintStep extends TaintTracking::AdditionalTaint
}
}
/**
* A data-flow node that logs data.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Logging::Range` instead.
*/
class Logging extends DataFlow::Node {
Logging::Range range;
Logging() { this = range }
/** Gets an input that is logged. */
DataFlow::Node getAnInput() { result = range.getAnInput() }
}
/** Provides a class for modeling new logging mechanisms. */
module Logging {
/**
* A data-flow node that logs data.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `Logging` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets an input that is logged. */
abstract DataFlow::Node getAnInput();
}
}
/**
* A data-flow node that dynamically executes Python code.
*

View File

@@ -93,6 +93,23 @@ class EncodingTest extends InlineExpectationsTest {
}
}
class LoggingTest extends InlineExpectationsTest {
LoggingTest() { this = "LoggingTest" }
override string getARelevantTag() { result in ["loggingInput"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(Logging logging, DataFlow::Node data |
location = data.getLocation() and
element = data.toString() and
value = prettyNodeForInlineTest(data) and
data = logging.getAnInput() and
tag = "loggingInput"
)
}
}
class CodeExecutionTest extends InlineExpectationsTest {
CodeExecutionTest() { this = "CodeExecutionTest" }

View File

@@ -0,0 +1,45 @@
import logging
# this bit just included to make this file runable
logging.basicConfig(level=logging.DEBUG)
password = "<pass>"
msg = "foo %s"
LOGGER = logging.getLogger("LOGGER")
logging.info(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.info(msg="hello") # $ MISSING: loggingInput="hello"
logging.log(logging.INFO, msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.log(logging.INFO, msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.root.info(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
# test of all levels
logging.critical(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.fatal(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.error(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.warning(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.warn(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.info(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.debug(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
logging.exception(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.critical(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.fatal(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.error(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.warning(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.warn(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.info(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.debug(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
LOGGER.exception(msg, password) # $ MISSING: loggingInput=msg loggingInput=password
# not sure how to make these print anything, but just to show that it works
logging.Logger("foo").info("hello") # $ MISSING: loggingInput="hello"
class MyLogger(logging.Logger):
pass
MyLogger("bar").info("hello") # $ MISSING: loggingInput="hello"