mirror of
https://github.com/github/codeql.git
synced 2026-06-19 03:41:07 +02:00
Merge branch 'main' into bazookamusic/cwe-1427
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* @github/code-scanning-alert-coverage
|
||||
|
||||
# CodeQL language libraries
|
||||
/actions/ @github/codeql-dynamic
|
||||
/actions/ @github/code-scanning-alert-coverage
|
||||
/cpp/ @github/codeql-c-analysis
|
||||
/csharp/ @github/codeql-csharp
|
||||
/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor @github/code-scanning-language-coverage
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @name Checkout of untrusted code in a trusted context
|
||||
* @description Privileged workflows have read/write access to the base repository and access to secrets.
|
||||
* By explicitly checking out and running the build script from a fork the untrusted code is running in an environment
|
||||
* that is able to push to the base repository and to access secrets.
|
||||
* @name Checkout of untrusted code in a non-privileged context
|
||||
* @description Checking out and running the build script from a fork executes untrusted code. Even in a
|
||||
* non-privileged workflow, this can be abused, for example to compromise self-hosted runners
|
||||
* or to poison caches and artifacts that are later consumed by privileged workflows.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
@@ -20,4 +20,4 @@ from PRHeadCheckoutStep checkout
|
||||
where
|
||||
// the checkout occurs in a non-privileged context
|
||||
inNonPrivilegedContext(checkout)
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on privileged workflow."
|
||||
select checkout, "Potential unsafe checkout of untrusted pull request on non-privileged workflow."
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: queryMetadata
|
||||
---
|
||||
* The name, description, and alert message of `actions/untrusted-checkout/medium` have been corrected to describe a non-privileged context.
|
||||
@@ -1,10 +1,10 @@
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on privileged workflow. |
|
||||
| .github/workflows/artifactpoisoning81.yml:11:9:14:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/dependabot2.yml:33:9:38:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/mend.yml:22:9:29:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc3.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/poc.yml:30:9:36:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/priv_pull_request_checkout.yml:14:9:20:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test3.yml:28:9:33:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test4.yml:18:7:25:4 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test8.yml:20:9:26:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
| .github/workflows/test9.yml:11:9:16:6 | Uses Step | Potential unsafe checkout of untrusted pull request on non-privileged workflow. |
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* `FuncTypeExpr.getResultDecl()` has been deprecated. Use `FuncTypeExpr.getResultDecl(int i)` instead.
|
||||
4
go/ql/lib/change-notes/2026-06-08-fix-result-nodes.md
Normal file
4
go/ql/lib/change-notes/2026-06-08-fix-result-nodes.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DataFlow::ResultNode`s are no longer created for returned expressions in functions with named result parameters. In this case there are already result nodes corresponding to `IR::ReadResultInstruction`s at the end of the function body.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FuncTypeExpr.getNumResult()` now gets the number of result parameters. It previously got the number of result declarations, which is different when one result declaration declares more than one variable, as in `x, y int`. All uses of it expected the number of result parameters. Its QLDoc has been updated.
|
||||
@@ -1049,17 +1049,29 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
*/
|
||||
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
|
||||
|
||||
/** Gets the `i`th result of this function type (0-based). */
|
||||
/**
|
||||
* Gets the `i`th result declaration of this function type (0-based).
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
|
||||
|
||||
/** Gets a result of this function type. */
|
||||
/**
|
||||
* Gets a result declaration of this function type.
|
||||
*
|
||||
* Note: `x, y int` is a single `ResultVariableDecl`.
|
||||
*/
|
||||
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
|
||||
|
||||
/** Gets the number of results of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl()) }
|
||||
/** Gets the number of result parameters of this function type. */
|
||||
int getNumResult() { result = count(this.getAResultDecl().getANameExpr()) }
|
||||
|
||||
/** Gets the result of this function type, if there is only one. */
|
||||
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
|
||||
/**
|
||||
* DEPRECATED: Use `getResultDecl(int i)` instead.
|
||||
*/
|
||||
deprecated ResultVariableDecl getResultDecl() {
|
||||
this.getNumResult() = 1 and result = this.getAResultDecl()
|
||||
}
|
||||
|
||||
override string toString() { result = "function type" }
|
||||
|
||||
|
||||
@@ -923,15 +923,20 @@ module Public {
|
||||
/**
|
||||
* A node whose value is returned as a result from a function.
|
||||
*
|
||||
* This can either be a node corresponding to an expression in a return statement,
|
||||
* or a node representing the current value of a named result variable at the exit
|
||||
* of the function.
|
||||
* If the function declares named result variables, this is a node representing
|
||||
* the current value of one of those variables at function exit. Otherwise, this
|
||||
* is a node corresponding to an expression in a return statement.
|
||||
*/
|
||||
class ResultNode extends InstructionNode {
|
||||
int i;
|
||||
|
||||
ResultNode() {
|
||||
exists(FuncDef fd |
|
||||
// If the function has named result variables, then the
|
||||
// `IR::ReadResultInstruction` nodes at the end of the function are
|
||||
// the correct result nodes. Otherwise, the returned expressions are
|
||||
// the result nodes.
|
||||
not exists(fd.getAResultVar()) and
|
||||
exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i))
|
||||
or
|
||||
insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i))
|
||||
|
||||
@@ -55,7 +55,7 @@ class SyncFileFun extends Method {
|
||||
|
||||
/**
|
||||
* Holds if a `call` to a function is "unhandled". That is, it is either
|
||||
* deferred or its result is not assigned to anything.
|
||||
* deferred or used as an expression statement, so that its result is discarded.
|
||||
*
|
||||
* TODO: maybe we should check that something is actually done with the result
|
||||
*/
|
||||
@@ -77,7 +77,6 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
|
||||
// get the flags expression used for opening the file
|
||||
call.getArgument(1) = flags and
|
||||
// extract individual flags from the argument
|
||||
// flag = flag.getAChild*() and
|
||||
flag = getConstants(flags.asExpr()) and
|
||||
// check for one which signals that the handle will be writable
|
||||
// note that we are underestimating here, since the flags may be
|
||||
@@ -87,27 +86,18 @@ predicate isWritableFileHandle(DataFlow::Node source, DataFlow::CallNode call) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `os.File.Close` is called on `sink`.
|
||||
* Holds if `postDominator` post-dominates `node` in the control-flow graph. That is,
|
||||
* every path from `node` to the exit of the enclosing function passes through
|
||||
* `postDominator`.
|
||||
*/
|
||||
predicate isCloseSink(DataFlow::Node sink, DataFlow::CallNode closeCall) {
|
||||
// find calls to the os.File.Close function
|
||||
closeCall = any(CloseFileFun f).getACall() and
|
||||
// that are unhandled
|
||||
unhandledCall(closeCall) and
|
||||
// where the function is called on the sink
|
||||
closeCall.getReceiver() = sink and
|
||||
// and check that it is not dominated by a call to `os.File.Sync`.
|
||||
// TODO: fix this logic when `closeCall` is in a defer statement.
|
||||
not exists(IR::Instruction syncInstr, DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
|
||||
// match the instruction corresponding to an `os.File.Sync` call with the predecessor
|
||||
syncCall.asInstruction() = syncInstr and
|
||||
// check that the call to `os.File.Sync` is handled
|
||||
isHandledSync(syncReceiver, syncCall) and
|
||||
// find a predecessor to `closeCall` in the control flow graph which dominates the call to
|
||||
// `os.File.Close`
|
||||
syncInstr.dominatesNode(closeCall.asInstruction()) and
|
||||
// check that `os.File.Sync` is called on the same object as `os.File.Close`
|
||||
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
|
||||
pragma[inline]
|
||||
predicate postDominatesNode(ControlFlow::Node postDominator, ControlFlow::Node node) {
|
||||
exists(ReachableBasicBlock pdbb, ReachableBasicBlock nbb, int i, int j |
|
||||
postDominator = pdbb.getNode(i) and node = nbb.getNode(j)
|
||||
|
|
||||
pdbb.strictlyPostDominates(nbb)
|
||||
or
|
||||
pdbb = nbb and i >= j
|
||||
)
|
||||
}
|
||||
|
||||
@@ -127,7 +117,39 @@ predicate isHandledSync(DataFlow::Node sink, DataFlow::CallNode syncCall) {
|
||||
module UnhandledFileCloseConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isWritableFileHandle(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isCloseSink(sink, _) }
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(DataFlow::CallNode closeCall |
|
||||
// `closeCall` is an unhandled call to `os.File.Close` on `sink`
|
||||
closeCall = any(CloseFileFun f).getACall() and
|
||||
unhandledCall(closeCall) and
|
||||
closeCall.getReceiver() = sink
|
||||
|
|
||||
// `closeCall` is not guaranteed to be preceded during
|
||||
// execution by a handled call to `os.File.Sync` on the same file handle.
|
||||
not exists(DataFlow::Node syncReceiver, DataFlow::CallNode syncCall |
|
||||
// check that the call to `os.File.Sync` is handled
|
||||
isHandledSync(syncReceiver, syncCall) and
|
||||
// check that `os.File.Sync` is called on the same object as `os.File.Close`
|
||||
exists(DataFlow::SsaNode ssa | ssa.getAUse() = sink and ssa.getAUse() = syncReceiver)
|
||||
|
|
||||
if exists(DeferStmt defer | defer.getCall() = closeCall.asExpr())
|
||||
then
|
||||
// When the call to `os.File.Close` is deferred it runs when the enclosing function
|
||||
// returns, but the receiver of the deferred call is evaluated where the `defer`
|
||||
// statement appears. It is therefore enough for the handled call to `os.File.Sync`
|
||||
// to post-dominate that point, since that guarantees `os.File.Sync` runs before the
|
||||
// deferred `os.File.Close` on every path on which the `os.File.Close` is registered.
|
||||
// We cannot reuse the domination check below because the control-flow graph splices
|
||||
// the deferred call in at the function exit, where it may be reachable along paths
|
||||
// that do not pass through the call to `os.File.Sync`.
|
||||
postDominatesNode(syncCall.asInstruction(), sink.asInstruction())
|
||||
else
|
||||
// Otherwise the call to `os.File.Close` is executed where it appears, so we require
|
||||
// the handled call to `os.File.Sync` to dominate it.
|
||||
syncCall.asInstruction().dominatesNode(closeCall.asInstruction())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
|
||||
@@ -148,14 +170,12 @@ import UnhandledFileCloseFlow::PathGraph
|
||||
|
||||
from
|
||||
UnhandledFileCloseFlow::PathNode source, DataFlow::CallNode openCall,
|
||||
UnhandledFileCloseFlow::PathNode sink, DataFlow::CallNode closeCall
|
||||
UnhandledFileCloseFlow::PathNode sink
|
||||
where
|
||||
// find data flow from an `os.OpenFile` call to an `os.File.Close` call
|
||||
// where the handle is writable
|
||||
UnhandledFileCloseFlow::flowPath(source, sink) and
|
||||
isWritableFileHandle(source.getNode(), openCall) and
|
||||
// get the `CallNode` corresponding to the sink
|
||||
isCloseSink(sink.getNode(), closeCall)
|
||||
isWritableFileHandle(source.getNode(), openCall)
|
||||
select sink, source, sink,
|
||||
"File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly.",
|
||||
openCall, openCall.toString()
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The query `go/unhandled-writable-file-close` ("Writable file handle closed without error handling") now produces fewer false positives. A deferred call to `Close` that is preceded on every execution path by a handled call to `Sync` on the same file handle is no longer flagged.
|
||||
@@ -735,129 +735,153 @@
|
||||
| main.go:48:11:48:12 | 42 | main.go:48:2:48:7 | assignment to result |
|
||||
| main.go:49:2:49:7 | return statement | main.go:47:13:47:18 | implicit read of result |
|
||||
| main.go:52:1:54:1 | entry | main.go:52:14:52:19 | zero value for result |
|
||||
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:10 | skip |
|
||||
| main.go:52:1:54:1 | function declaration | main.go:56:6:56:9 | skip |
|
||||
| main.go:52:6:52:9 | skip | main.go:52:1:54:1 | function declaration |
|
||||
| main.go:52:14:52:19 | implicit read of result | main.go:52:1:54:1 | exit |
|
||||
| main.go:52:14:52:19 | initialization of result | main.go:53:2:53:7 | return statement |
|
||||
| main.go:52:14:52:19 | zero value for result | main.go:52:14:52:19 | initialization of result |
|
||||
| main.go:53:2:53:7 | return statement | main.go:52:14:52:19 | implicit read of result |
|
||||
| main.go:56:1:80:1 | entry | main.go:57:6:57:6 | skip |
|
||||
| main.go:56:1:80:1 | function declaration | main.go:82:6:82:13 | skip |
|
||||
| main.go:56:6:56:10 | skip | main.go:56:1:80:1 | function declaration |
|
||||
| main.go:57:6:57:6 | assignment to x | main.go:58:6:58:9 | cond |
|
||||
| main.go:57:6:57:6 | skip | main.go:57:6:57:6 | zero value for x |
|
||||
| main.go:57:6:57:6 | zero value for x | main.go:57:6:57:6 | assignment to x |
|
||||
| main.go:58:6:58:9 | cond | main.go:58:6:58:11 | call to cond |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is false |
|
||||
| main.go:58:6:58:11 | call to cond | main.go:58:6:58:11 | call to cond is true |
|
||||
| main.go:58:6:58:11 | call to cond is false | main.go:61:2:61:10 | selection of Print |
|
||||
| main.go:58:6:58:11 | call to cond is true | main.go:59:3:59:3 | skip |
|
||||
| main.go:59:3:59:3 | assignment to x | main.go:58:6:58:9 | cond |
|
||||
| main.go:59:3:59:3 | skip | main.go:59:7:59:7 | 2 |
|
||||
| main.go:59:7:59:7 | 2 | main.go:59:3:59:3 | assignment to x |
|
||||
| main.go:61:2:61:10 | selection of Print | main.go:61:12:61:12 | x |
|
||||
| main.go:61:2:61:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:61:2:61:13 | call to Print | main.go:63:2:63:2 | skip |
|
||||
| main.go:61:12:61:12 | x | main.go:61:2:61:13 | call to Print |
|
||||
| main.go:63:2:63:2 | assignment to y | main.go:64:6:64:6 | skip |
|
||||
| main.go:63:2:63:2 | skip | main.go:63:7:63:7 | 1 |
|
||||
| main.go:63:7:63:7 | 1 | main.go:63:2:63:2 | assignment to y |
|
||||
| main.go:64:6:64:6 | assignment to i | main.go:65:6:65:9 | cond |
|
||||
| main.go:64:6:64:6 | skip | main.go:64:11:64:11 | 0 |
|
||||
| main.go:64:11:64:11 | 0 | main.go:64:6:64:6 | assignment to i |
|
||||
| main.go:64:16:64:16 | i | main.go:64:16:64:18 | 1 |
|
||||
| main.go:64:16:64:18 | 1 | main.go:64:16:64:18 | rhs of increment statement |
|
||||
| main.go:64:16:64:18 | increment statement | main.go:65:6:65:9 | cond |
|
||||
| main.go:64:16:64:18 | rhs of increment statement | main.go:64:16:64:18 | increment statement |
|
||||
| main.go:65:6:65:9 | cond | main.go:65:6:65:11 | call to cond |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is false |
|
||||
| main.go:65:6:65:11 | call to cond | main.go:65:6:65:11 | call to cond is true |
|
||||
| main.go:65:6:65:11 | call to cond is false | main.go:68:3:68:3 | skip |
|
||||
| main.go:65:6:65:11 | call to cond is true | main.go:66:4:66:8 | skip |
|
||||
| main.go:66:4:66:8 | skip | main.go:70:2:70:10 | selection of Print |
|
||||
| main.go:68:3:68:3 | assignment to y | main.go:64:16:64:16 | i |
|
||||
| main.go:68:3:68:3 | skip | main.go:68:7:68:7 | 2 |
|
||||
| main.go:68:7:68:7 | 2 | main.go:68:3:68:3 | assignment to y |
|
||||
| main.go:70:2:70:10 | selection of Print | main.go:70:12:70:12 | y |
|
||||
| main.go:70:2:70:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:70:2:70:13 | call to Print | main.go:72:2:72:2 | skip |
|
||||
| main.go:70:12:70:12 | y | main.go:70:2:70:13 | call to Print |
|
||||
| main.go:72:2:72:2 | assignment to z | main.go:73:6:73:6 | skip |
|
||||
| main.go:72:2:72:2 | skip | main.go:72:7:72:7 | 1 |
|
||||
| main.go:72:7:72:7 | 1 | main.go:72:2:72:2 | assignment to z |
|
||||
| main.go:73:6:73:6 | assignment to i | main.go:74:3:74:3 | skip |
|
||||
| main.go:73:6:73:6 | skip | main.go:73:11:73:11 | 0 |
|
||||
| main.go:73:11:73:11 | 0 | main.go:73:6:73:6 | assignment to i |
|
||||
| main.go:73:16:73:16 | i | main.go:73:16:73:18 | 1 |
|
||||
| main.go:73:16:73:18 | 1 | main.go:73:16:73:18 | rhs of increment statement |
|
||||
| main.go:73:16:73:18 | increment statement | main.go:74:3:74:3 | skip |
|
||||
| main.go:73:16:73:18 | rhs of increment statement | main.go:73:16:73:18 | increment statement |
|
||||
| main.go:74:3:74:3 | assignment to z | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:3:74:3 | skip | main.go:74:7:74:7 | 2 |
|
||||
| main.go:74:7:74:7 | 2 | main.go:74:3:74:3 | assignment to z |
|
||||
| main.go:56:1:64:1 | entry | main.go:56:11:56:18 | argument corresponding to selector |
|
||||
| main.go:56:1:64:1 | function declaration | main.go:66:6:66:10 | skip |
|
||||
| main.go:56:6:56:9 | skip | main.go:56:1:64:1 | function declaration |
|
||||
| main.go:56:11:56:18 | argument corresponding to selector | main.go:56:11:56:18 | initialization of selector |
|
||||
| main.go:56:11:56:18 | initialization of selector | main.go:56:26:56:31 | zero value for result |
|
||||
| main.go:56:26:56:31 | implicit read of result | main.go:56:1:64:1 | exit |
|
||||
| main.go:56:26:56:31 | initialization of result | main.go:57:2:57:7 | skip |
|
||||
| main.go:56:26:56:31 | zero value for result | main.go:56:26:56:31 | initialization of result |
|
||||
| main.go:57:2:57:7 | assignment to result | main.go:58:5:58:12 | selector |
|
||||
| main.go:57:2:57:7 | skip | main.go:57:11:57:11 | 0 |
|
||||
| main.go:57:11:57:11 | 0 | main.go:57:2:57:7 | assignment to result |
|
||||
| main.go:58:5:58:12 | selector | main.go:58:17:58:17 | 1 |
|
||||
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is false |
|
||||
| main.go:58:5:58:17 | ...==... | main.go:58:5:58:17 | ...==... is true |
|
||||
| main.go:58:5:58:17 | ...==... is false | main.go:61:3:61:8 | skip |
|
||||
| main.go:58:5:58:17 | ...==... is true | main.go:59:10:59:10 | 1 |
|
||||
| main.go:58:17:58:17 | 1 | main.go:58:5:58:17 | ...==... |
|
||||
| main.go:59:3:59:10 | return statement | main.go:56:26:56:31 | implicit read of result |
|
||||
| main.go:59:10:59:10 | 1 | main.go:59:10:59:10 | implicit write of result |
|
||||
| main.go:59:10:59:10 | implicit write of result | main.go:59:3:59:10 | return statement |
|
||||
| main.go:61:3:61:8 | assignment to result | main.go:63:2:63:7 | return statement |
|
||||
| main.go:61:3:61:8 | skip | main.go:61:12:61:12 | 2 |
|
||||
| main.go:61:12:61:12 | 2 | main.go:61:3:61:8 | assignment to result |
|
||||
| main.go:63:2:63:7 | return statement | main.go:56:26:56:31 | implicit read of result |
|
||||
| main.go:66:1:90:1 | entry | main.go:67:6:67:6 | skip |
|
||||
| main.go:66:1:90:1 | function declaration | main.go:92:6:92:13 | skip |
|
||||
| main.go:66:6:66:10 | skip | main.go:66:1:90:1 | function declaration |
|
||||
| main.go:67:6:67:6 | assignment to x | main.go:68:6:68:9 | cond |
|
||||
| main.go:67:6:67:6 | skip | main.go:67:6:67:6 | zero value for x |
|
||||
| main.go:67:6:67:6 | zero value for x | main.go:67:6:67:6 | assignment to x |
|
||||
| main.go:68:6:68:9 | cond | main.go:68:6:68:11 | call to cond |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is false |
|
||||
| main.go:68:6:68:11 | call to cond | main.go:68:6:68:11 | call to cond is true |
|
||||
| main.go:68:6:68:11 | call to cond is false | main.go:71:2:71:10 | selection of Print |
|
||||
| main.go:68:6:68:11 | call to cond is true | main.go:69:3:69:3 | skip |
|
||||
| main.go:69:3:69:3 | assignment to x | main.go:68:6:68:9 | cond |
|
||||
| main.go:69:3:69:3 | skip | main.go:69:7:69:7 | 2 |
|
||||
| main.go:69:7:69:7 | 2 | main.go:69:3:69:3 | assignment to x |
|
||||
| main.go:71:2:71:10 | selection of Print | main.go:71:12:71:12 | x |
|
||||
| main.go:71:2:71:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:71:2:71:13 | call to Print | main.go:73:2:73:2 | skip |
|
||||
| main.go:71:12:71:12 | x | main.go:71:2:71:13 | call to Print |
|
||||
| main.go:73:2:73:2 | assignment to y | main.go:74:6:74:6 | skip |
|
||||
| main.go:73:2:73:2 | skip | main.go:73:7:73:7 | 1 |
|
||||
| main.go:73:7:73:7 | 1 | main.go:73:2:73:2 | assignment to y |
|
||||
| main.go:74:6:74:6 | assignment to i | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:6:74:6 | skip | main.go:74:11:74:11 | 0 |
|
||||
| main.go:74:11:74:11 | 0 | main.go:74:6:74:6 | assignment to i |
|
||||
| main.go:74:16:74:16 | i | main.go:74:16:74:18 | 1 |
|
||||
| main.go:74:16:74:18 | 1 | main.go:74:16:74:18 | rhs of increment statement |
|
||||
| main.go:74:16:74:18 | increment statement | main.go:75:6:75:9 | cond |
|
||||
| main.go:74:16:74:18 | rhs of increment statement | main.go:74:16:74:18 | increment statement |
|
||||
| main.go:75:6:75:9 | cond | main.go:75:6:75:11 | call to cond |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:56:1:80:1 | exit |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is false |
|
||||
| main.go:75:6:75:11 | call to cond | main.go:75:6:75:11 | call to cond is true |
|
||||
| main.go:75:6:75:11 | call to cond is false | main.go:73:16:73:16 | i |
|
||||
| main.go:75:6:75:11 | call to cond is false | main.go:78:3:78:3 | skip |
|
||||
| main.go:75:6:75:11 | call to cond is true | main.go:76:4:76:8 | skip |
|
||||
| main.go:76:4:76:8 | skip | main.go:79:2:79:10 | selection of Print |
|
||||
| main.go:79:2:79:10 | selection of Print | main.go:79:12:79:12 | z |
|
||||
| main.go:79:2:79:13 | call to Print | main.go:56:1:80:1 | exit |
|
||||
| main.go:79:12:79:12 | z | main.go:79:2:79:13 | call to Print |
|
||||
| main.go:82:1:86:1 | entry | main.go:82:18:82:18 | zero value for a |
|
||||
| main.go:82:1:86:1 | function declaration | main.go:88:6:88:23 | skip |
|
||||
| main.go:82:6:82:13 | skip | main.go:82:1:86:1 | function declaration |
|
||||
| main.go:82:18:82:18 | implicit read of a | main.go:82:25:82:25 | implicit read of b |
|
||||
| main.go:82:18:82:18 | initialization of a | main.go:82:25:82:25 | zero value for b |
|
||||
| main.go:82:18:82:18 | zero value for a | main.go:82:18:82:18 | initialization of a |
|
||||
| main.go:82:25:82:25 | implicit read of b | main.go:82:1:86:1 | exit |
|
||||
| main.go:82:25:82:25 | initialization of b | main.go:83:2:83:2 | skip |
|
||||
| main.go:82:25:82:25 | zero value for b | main.go:82:25:82:25 | initialization of b |
|
||||
| main.go:83:2:83:2 | assignment to x | main.go:84:2:84:2 | skip |
|
||||
| main.go:83:2:83:2 | skip | main.go:83:7:83:8 | 23 |
|
||||
| main.go:83:7:83:8 | 23 | main.go:83:2:83:2 | assignment to x |
|
||||
| main.go:84:2:84:2 | assignment to x | main.go:84:5:84:5 | assignment to a |
|
||||
| main.go:84:2:84:2 | skip | main.go:84:5:84:5 | skip |
|
||||
| main.go:84:5:84:5 | assignment to a | main.go:85:2:85:7 | return statement |
|
||||
| main.go:84:5:84:5 | skip | main.go:84:9:84:9 | x |
|
||||
| main.go:84:9:84:9 | x | main.go:84:11:84:12 | 19 |
|
||||
| main.go:84:9:84:12 | ...+... | main.go:84:15:84:15 | x |
|
||||
| main.go:84:11:84:12 | 19 | main.go:84:9:84:12 | ...+... |
|
||||
| main.go:84:15:84:15 | x | main.go:84:2:84:2 | assignment to x |
|
||||
| main.go:85:2:85:7 | return statement | main.go:82:18:82:18 | implicit read of a |
|
||||
| main.go:88:1:96:1 | entry | main.go:88:25:88:25 | argument corresponding to x |
|
||||
| main.go:88:1:96:1 | function declaration | main.go:0:0:0:0 | exit |
|
||||
| main.go:88:6:88:23 | skip | main.go:88:1:96:1 | function declaration |
|
||||
| main.go:88:25:88:25 | argument corresponding to x | main.go:88:25:88:25 | initialization of x |
|
||||
| main.go:88:25:88:25 | initialization of x | main.go:89:2:89:2 | skip |
|
||||
| main.go:89:2:89:2 | assignment to a | main.go:89:5:89:5 | assignment to b |
|
||||
| main.go:89:2:89:2 | skip | main.go:89:5:89:5 | skip |
|
||||
| main.go:89:5:89:5 | assignment to b | main.go:90:5:90:8 | cond |
|
||||
| main.go:89:5:89:5 | skip | main.go:89:10:89:10 | x |
|
||||
| main.go:89:10:89:10 | x | main.go:89:13:89:13 | 0 |
|
||||
| main.go:89:13:89:13 | 0 | main.go:89:2:89:2 | assignment to a |
|
||||
| main.go:90:5:90:8 | cond | main.go:90:5:90:10 | call to cond |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:88:1:96:1 | exit |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is false |
|
||||
| main.go:90:5:90:10 | call to cond | main.go:90:5:90:10 | call to cond is true |
|
||||
| main.go:90:5:90:10 | call to cond is false | main.go:93:3:93:3 | skip |
|
||||
| main.go:90:5:90:10 | call to cond is true | main.go:91:3:91:3 | skip |
|
||||
| main.go:91:3:91:3 | assignment to a | main.go:95:9:95:9 | a |
|
||||
| main.go:91:3:91:3 | skip | main.go:91:6:91:6 | skip |
|
||||
| main.go:91:6:91:6 | skip | main.go:91:10:91:10 | b |
|
||||
| main.go:91:10:91:10 | b | main.go:91:13:91:13 | a |
|
||||
| main.go:91:13:91:13 | a | main.go:91:3:91:3 | assignment to a |
|
||||
| main.go:93:3:93:3 | skip | main.go:93:6:93:6 | skip |
|
||||
| main.go:93:6:93:6 | assignment to b | main.go:95:9:95:9 | a |
|
||||
| main.go:93:6:93:6 | skip | main.go:93:10:93:10 | b |
|
||||
| main.go:93:10:93:10 | b | main.go:93:13:93:13 | a |
|
||||
| main.go:93:13:93:13 | a | main.go:93:6:93:6 | assignment to b |
|
||||
| main.go:95:2:95:12 | return statement | main.go:88:1:96:1 | exit |
|
||||
| main.go:95:9:95:9 | a | main.go:95:12:95:12 | b |
|
||||
| main.go:95:12:95:12 | b | main.go:95:2:95:12 | return statement |
|
||||
| main.go:76:4:76:8 | skip | main.go:80:2:80:10 | selection of Print |
|
||||
| main.go:78:3:78:3 | assignment to y | main.go:74:16:74:16 | i |
|
||||
| main.go:78:3:78:3 | skip | main.go:78:7:78:7 | 2 |
|
||||
| main.go:78:7:78:7 | 2 | main.go:78:3:78:3 | assignment to y |
|
||||
| main.go:80:2:80:10 | selection of Print | main.go:80:12:80:12 | y |
|
||||
| main.go:80:2:80:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:80:2:80:13 | call to Print | main.go:82:2:82:2 | skip |
|
||||
| main.go:80:12:80:12 | y | main.go:80:2:80:13 | call to Print |
|
||||
| main.go:82:2:82:2 | assignment to z | main.go:83:6:83:6 | skip |
|
||||
| main.go:82:2:82:2 | skip | main.go:82:7:82:7 | 1 |
|
||||
| main.go:82:7:82:7 | 1 | main.go:82:2:82:2 | assignment to z |
|
||||
| main.go:83:6:83:6 | assignment to i | main.go:84:3:84:3 | skip |
|
||||
| main.go:83:6:83:6 | skip | main.go:83:11:83:11 | 0 |
|
||||
| main.go:83:11:83:11 | 0 | main.go:83:6:83:6 | assignment to i |
|
||||
| main.go:83:16:83:16 | i | main.go:83:16:83:18 | 1 |
|
||||
| main.go:83:16:83:18 | 1 | main.go:83:16:83:18 | rhs of increment statement |
|
||||
| main.go:83:16:83:18 | increment statement | main.go:84:3:84:3 | skip |
|
||||
| main.go:83:16:83:18 | rhs of increment statement | main.go:83:16:83:18 | increment statement |
|
||||
| main.go:84:3:84:3 | assignment to z | main.go:85:6:85:9 | cond |
|
||||
| main.go:84:3:84:3 | skip | main.go:84:7:84:7 | 2 |
|
||||
| main.go:84:7:84:7 | 2 | main.go:84:3:84:3 | assignment to z |
|
||||
| main.go:85:6:85:9 | cond | main.go:85:6:85:11 | call to cond |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:66:1:90:1 | exit |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is false |
|
||||
| main.go:85:6:85:11 | call to cond | main.go:85:6:85:11 | call to cond is true |
|
||||
| main.go:85:6:85:11 | call to cond is false | main.go:83:16:83:16 | i |
|
||||
| main.go:85:6:85:11 | call to cond is true | main.go:86:4:86:8 | skip |
|
||||
| main.go:86:4:86:8 | skip | main.go:89:2:89:10 | selection of Print |
|
||||
| main.go:89:2:89:10 | selection of Print | main.go:89:12:89:12 | z |
|
||||
| main.go:89:2:89:13 | call to Print | main.go:66:1:90:1 | exit |
|
||||
| main.go:89:12:89:12 | z | main.go:89:2:89:13 | call to Print |
|
||||
| main.go:92:1:96:1 | entry | main.go:92:18:92:18 | zero value for a |
|
||||
| main.go:92:1:96:1 | function declaration | main.go:98:6:98:23 | skip |
|
||||
| main.go:92:6:92:13 | skip | main.go:92:1:96:1 | function declaration |
|
||||
| main.go:92:18:92:18 | implicit read of a | main.go:92:25:92:25 | implicit read of b |
|
||||
| main.go:92:18:92:18 | initialization of a | main.go:92:25:92:25 | zero value for b |
|
||||
| main.go:92:18:92:18 | zero value for a | main.go:92:18:92:18 | initialization of a |
|
||||
| main.go:92:25:92:25 | implicit read of b | main.go:92:1:96:1 | exit |
|
||||
| main.go:92:25:92:25 | initialization of b | main.go:93:2:93:2 | skip |
|
||||
| main.go:92:25:92:25 | zero value for b | main.go:92:25:92:25 | initialization of b |
|
||||
| main.go:93:2:93:2 | assignment to x | main.go:94:2:94:2 | skip |
|
||||
| main.go:93:2:93:2 | skip | main.go:93:7:93:8 | 23 |
|
||||
| main.go:93:7:93:8 | 23 | main.go:93:2:93:2 | assignment to x |
|
||||
| main.go:94:2:94:2 | assignment to x | main.go:94:5:94:5 | assignment to a |
|
||||
| main.go:94:2:94:2 | skip | main.go:94:5:94:5 | skip |
|
||||
| main.go:94:5:94:5 | assignment to a | main.go:95:2:95:7 | return statement |
|
||||
| main.go:94:5:94:5 | skip | main.go:94:9:94:9 | x |
|
||||
| main.go:94:9:94:9 | x | main.go:94:11:94:12 | 19 |
|
||||
| main.go:94:9:94:12 | ...+... | main.go:94:15:94:15 | x |
|
||||
| main.go:94:11:94:12 | 19 | main.go:94:9:94:12 | ...+... |
|
||||
| main.go:94:15:94:15 | x | main.go:94:2:94:2 | assignment to x |
|
||||
| main.go:95:2:95:7 | return statement | main.go:92:18:92:18 | implicit read of a |
|
||||
| main.go:98:1:106:1 | entry | main.go:98:25:98:25 | argument corresponding to x |
|
||||
| main.go:98:1:106:1 | function declaration | main.go:0:0:0:0 | exit |
|
||||
| main.go:98:6:98:23 | skip | main.go:98:1:106:1 | function declaration |
|
||||
| main.go:98:25:98:25 | argument corresponding to x | main.go:98:25:98:25 | initialization of x |
|
||||
| main.go:98:25:98:25 | initialization of x | main.go:99:2:99:2 | skip |
|
||||
| main.go:99:2:99:2 | assignment to a | main.go:99:5:99:5 | assignment to b |
|
||||
| main.go:99:2:99:2 | skip | main.go:99:5:99:5 | skip |
|
||||
| main.go:99:5:99:5 | assignment to b | main.go:100:5:100:8 | cond |
|
||||
| main.go:99:5:99:5 | skip | main.go:99:10:99:10 | x |
|
||||
| main.go:99:10:99:10 | x | main.go:99:13:99:13 | 0 |
|
||||
| main.go:99:13:99:13 | 0 | main.go:99:2:99:2 | assignment to a |
|
||||
| main.go:100:5:100:8 | cond | main.go:100:5:100:10 | call to cond |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:98:1:106:1 | exit |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is false |
|
||||
| main.go:100:5:100:10 | call to cond | main.go:100:5:100:10 | call to cond is true |
|
||||
| main.go:100:5:100:10 | call to cond is false | main.go:103:3:103:3 | skip |
|
||||
| main.go:100:5:100:10 | call to cond is true | main.go:101:3:101:3 | skip |
|
||||
| main.go:101:3:101:3 | assignment to a | main.go:105:9:105:9 | a |
|
||||
| main.go:101:3:101:3 | skip | main.go:101:6:101:6 | skip |
|
||||
| main.go:101:6:101:6 | skip | main.go:101:10:101:10 | b |
|
||||
| main.go:101:10:101:10 | b | main.go:101:13:101:13 | a |
|
||||
| main.go:101:13:101:13 | a | main.go:101:3:101:3 | assignment to a |
|
||||
| main.go:103:3:103:3 | skip | main.go:103:6:103:6 | skip |
|
||||
| main.go:103:6:103:6 | assignment to b | main.go:105:9:105:9 | a |
|
||||
| main.go:103:6:103:6 | skip | main.go:103:10:103:10 | b |
|
||||
| main.go:103:10:103:10 | b | main.go:103:13:103:13 | a |
|
||||
| main.go:103:13:103:13 | a | main.go:103:6:103:6 | assignment to b |
|
||||
| main.go:105:2:105:12 | return statement | main.go:98:1:106:1 | exit |
|
||||
| main.go:105:9:105:9 | a | main.go:105:12:105:12 | b |
|
||||
| main.go:105:12:105:12 | b | main.go:105:2:105:12 | return statement |
|
||||
| noretfunctions.go:0:0:0:0 | entry | noretfunctions.go:3:1:6:1 | skip |
|
||||
| noretfunctions.go:3:1:6:1 | skip | noretfunctions.go:8:6:8:12 | skip |
|
||||
| noretfunctions.go:8:1:10:1 | entry | noretfunctions.go:9:2:9:8 | selection of Exit |
|
||||
|
||||
@@ -53,6 +53,16 @@ func baz2() (result int) {
|
||||
return
|
||||
}
|
||||
|
||||
func baz3(selector int) (result int) {
|
||||
result = 0
|
||||
if selector == 1 {
|
||||
return 1
|
||||
} else {
|
||||
result = 2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func loops() {
|
||||
var x int
|
||||
for cond() {
|
||||
|
||||
@@ -2,3 +2,5 @@
|
||||
| main.go:7:19:7:23 | ...+... | + | main.go:7:19:7:19 | y | main.go:7:23:7:23 | z |
|
||||
| main.go:10:14:10:18 | ...+... | + | main.go:10:14:10:14 | x | main.go:10:18:10:18 | y |
|
||||
| main.go:17:2:17:13 | ... += ... | + | main.go:17:2:17:6 | index expression | main.go:17:11:17:13 | "!" |
|
||||
| resultParameters.go:4:5:4:17 | ...==... | == | resultParameters.go:4:5:4:12 | selector | resultParameters.go:4:17:4:17 | 0 |
|
||||
| resultParameters.go:23:5:23:17 | ...==... | == | resultParameters.go:23:5:23:12 | selector | resultParameters.go:23:17:23:17 | 1 |
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
| main.go:21:9:21:10 | 23 | Result node with index 0 |
|
||||
| main.go:21:13:21:14 | 42 | Result node with index 1 |
|
||||
| resultParameters.go:5:10:5:10 | 0 | Result node with index 0 |
|
||||
| resultParameters.go:9:10:9:10 | 1 | Result node with index 0 |
|
||||
| resultParameters.go:11:10:11:10 | 2 | Result node with index 0 |
|
||||
| resultParameters.go:13:9:13:9 | 3 | Result node with index 0 |
|
||||
| resultParameters.go:16:26:16:26 | implicit read of r | Result node with index 0 |
|
||||
| resultParameters.go:21:38:21:38 | implicit read of r | Result node with index 0 |
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @kind problem
|
||||
* @id result-node
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
from DataFlow::ResultNode r
|
||||
select r, "Result node with index " + r.getIndex()
|
||||
@@ -0,0 +1,2 @@
|
||||
query: ResultNode.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -18,5 +18,5 @@ func f() {
|
||||
}
|
||||
|
||||
func test() (int, int) {
|
||||
return 23, 42
|
||||
return 23, 42 // $ Alert[result-node]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
func multipleReturns(selector int) int {
|
||||
if selector == 0 {
|
||||
return 0 // $ Alert[result-node]
|
||||
}
|
||||
switch selector {
|
||||
case 1:
|
||||
return 1 // $ Alert[result-node]
|
||||
case 2:
|
||||
return 2 // $ Alert[result-node]
|
||||
}
|
||||
return 3 // $ Alert[result-node]
|
||||
}
|
||||
|
||||
func resultParameter1() (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
|
||||
r = 0
|
||||
return
|
||||
}
|
||||
|
||||
func resultParameter2(selector int) (r int) { // $ Alert[result-node] // implicit reads of result parameters are located at the result parameter declaration
|
||||
r = 0
|
||||
if selector == 1 {
|
||||
return 1
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -5,9 +5,9 @@
|
||||
| tests.go:15:3:15:3 | f | tests.go:46:5:46:76 | ... := ...[0] | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:57:3:57:3 | f | tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:55:15:55:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:69:3:69:3 | f | tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:67:15:67:76 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:111:9:111:9 | f | tests.go:109:5:109:78 | ... := ...[0] | tests.go:111:9:111:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:109:15:109:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:130:3:130:3 | f | tests.go:126:5:126:78 | ... := ...[0] | tests.go:130:3:130:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:126:15:126:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:151:8:151:8 | f | tests.go:147:2:147:74 | ... := ...[0] | tests.go:151:8:151:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:147:12:147:74 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:126:9:126:9 | f | tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:124:15:124:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:145:3:145:3 | f | tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:141:15:141:78 | call to OpenFile | call to OpenFile |
|
||||
| tests.go:166:8:166:8 | f | tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:162:12:162:74 | call to OpenFile | call to OpenFile |
|
||||
edges
|
||||
| tests.go:9:24:9:24 | definition of f | tests.go:10:8:10:8 | f | provenance | |
|
||||
| tests.go:13:32:13:32 | definition of f | tests.go:14:13:16:2 | capture variable f | provenance | |
|
||||
@@ -22,9 +22,9 @@ edges
|
||||
| tests.go:48:29:48:29 | f | tests.go:13:32:13:32 | definition of f | provenance | |
|
||||
| tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:109:5:109:78 | ... := ...[0] | tests.go:111:9:111:9 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:126:5:126:78 | ... := ...[0] | tests.go:130:3:130:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:147:2:147:74 | ... := ...[0] | tests.go:151:8:151:8 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | provenance | Src:MaD:1 |
|
||||
| tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | provenance | Src:MaD:1 |
|
||||
models
|
||||
| 1 | Source: os; ; false; OpenFile; ; ; ReturnValue[0]; file; manual |
|
||||
nodes
|
||||
@@ -43,10 +43,10 @@ nodes
|
||||
| tests.go:57:3:57:3 | f | semmle.label | f |
|
||||
| tests.go:67:5:67:76 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:69:3:69:3 | f | semmle.label | f |
|
||||
| tests.go:109:5:109:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:111:9:111:9 | f | semmle.label | f |
|
||||
| tests.go:126:5:126:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:130:3:130:3 | f | semmle.label | f |
|
||||
| tests.go:147:2:147:74 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:151:8:151:8 | f | semmle.label | f |
|
||||
| tests.go:124:5:124:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:126:9:126:9 | f | semmle.label | f |
|
||||
| tests.go:141:5:141:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:145:3:145:3 | f | semmle.label | f |
|
||||
| tests.go:162:2:162:74 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||
| tests.go:166:8:166:8 | f | semmle.label | f |
|
||||
subpaths
|
||||
|
||||
@@ -104,6 +104,21 @@ func deferredCloseWithSync() {
|
||||
}
|
||||
}
|
||||
|
||||
func deferredCloseWithSync2() {
|
||||
// open file for writing
|
||||
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
|
||||
// a call to `Close` is deferred, but we have a call to `Sync` later which
|
||||
// precedes the call to `Close` during execution
|
||||
defer f.Close()
|
||||
|
||||
if err := f.Sync(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
var a int
|
||||
_ = a
|
||||
}
|
||||
|
||||
func deferredCloseWithSyncEarlyReturn(n int) {
|
||||
// open file for writing
|
||||
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil { // $ Source
|
||||
|
||||
Reference in New Issue
Block a user