Improve test for UnhandledCloseWritableHandle

Now the different paths won't have the same two sources.
This commit is contained in:
Owen Mansel-Chan
2023-11-28 14:21:43 +00:00
parent f05c86239f
commit 57dafd3732
2 changed files with 62 additions and 74 deletions

View File

@@ -1,56 +1,46 @@
edges
| tests.go:9:2:9:74 | ... := ...[0] | tests.go:10:9:10:9 | f |
| tests.go:10:9:10:9 | f | tests.go:43:5:43:38 | ... := ...[0] |
| tests.go:10:9:10:9 | f | tests.go:60:5:60:38 | ... := ...[0] |
| tests.go:10:9:10:9 | f | tests.go:108:5:108:38 | ... := ...[0] |
| tests.go:10:9:10:9 | f | tests.go:124:5:124:38 | ... := ...[0] |
| tests.go:18:2:18:69 | return statement[0] | tests.go:53:5:53:42 | ... := ...[0] |
| tests.go:18:2:18:69 | return statement[0] | tests.go:70:5:70:42 | ... := ...[0] |
| tests.go:21:24:21:24 | definition of f | tests.go:22:8:22:8 | f |
| tests.go:25:32:25:32 | definition of f | tests.go:26:13:26:13 | capture variable f |
| tests.go:26:13:26:13 | capture variable f | tests.go:27:3:27:3 | f |
| tests.go:43:5:43:38 | ... := ...[0] | tests.go:44:21:44:21 | f |
| tests.go:43:5:43:38 | ... := ...[0] | tests.go:45:29:45:29 | f |
| tests.go:44:21:44:21 | f | tests.go:21:24:21:24 | definition of f |
| tests.go:45:29:45:29 | f | tests.go:25:32:25:32 | definition of f |
| tests.go:53:5:53:42 | ... := ...[0] | tests.go:54:21:54:21 | f |
| tests.go:53:5:53:42 | ... := ...[0] | tests.go:55:29:55:29 | f |
| tests.go:54:21:54:21 | f | tests.go:21:24:21:24 | definition of f |
| tests.go:55:29:55:29 | f | tests.go:25:32:25:32 | definition of f |
| tests.go:60:5:60:38 | ... := ...[0] | tests.go:62:3:62:3 | f |
| tests.go:70:5:70:42 | ... := ...[0] | tests.go:72:3:72:3 | f |
| tests.go:108:5:108:38 | ... := ...[0] | tests.go:110:9:110:9 | f |
| tests.go:124:5:124:38 | ... := ...[0] | tests.go:128:3:128:3 | f |
| tests.go:8:24:8:24 | definition of f | tests.go:9:8:9:8 | f |
| tests.go:12:32:12:32 | definition of f | tests.go:13:13:13:13 | capture variable f |
| tests.go:13:13:13:13 | capture variable f | tests.go:14:3:14:3 | f |
| tests.go:31:5:31:78 | ... := ...[0] | tests.go:32:21:32:21 | f |
| tests.go:31:5:31:78 | ... := ...[0] | tests.go:33:29:33:29 | f |
| tests.go:32:21:32:21 | f | tests.go:8:24:8:24 | definition of f |
| tests.go:33:29:33:29 | f | tests.go:12:32:12:32 | definition of f |
| tests.go:43:5:43:76 | ... := ...[0] | tests.go:44:21:44:21 | f |
| tests.go:43:5:43:76 | ... := ...[0] | tests.go:45:29:45:29 | f |
| tests.go:44:21:44:21 | f | tests.go:8:24:8:24 | definition of f |
| tests.go:45:29:45:29 | f | tests.go:12:32:12:32 | definition of f |
| tests.go:51:5:51:78 | ... := ...[0] | tests.go:53:3:53:3 | f |
| tests.go:63:5:63:76 | ... := ...[0] | tests.go:65:3:65:3 | f |
| tests.go:105:5:105:78 | ... := ...[0] | tests.go:107:9:107:9 | f |
| tests.go:122:5:122:78 | ... := ...[0] | tests.go:126:3:126:3 | f |
nodes
| tests.go:9:2:9:74 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:10:9:10:9 | f | semmle.label | f |
| tests.go:18:2:18:69 | return statement[0] | semmle.label | return statement[0] |
| tests.go:21:24:21:24 | definition of f | semmle.label | definition of f |
| tests.go:22:8:22:8 | f | semmle.label | f |
| tests.go:25:32:25:32 | definition of f | semmle.label | definition of f |
| tests.go:26:13:26:13 | capture variable f | semmle.label | capture variable f |
| tests.go:27:3:27:3 | f | semmle.label | f |
| tests.go:43:5:43:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:8:24:8:24 | definition of f | semmle.label | definition of f |
| tests.go:9:8:9:8 | f | semmle.label | f |
| tests.go:12:32:12:32 | definition of f | semmle.label | definition of f |
| tests.go:13:13:13:13 | capture variable f | semmle.label | capture variable f |
| tests.go:14:3:14:3 | f | semmle.label | f |
| tests.go:31:5:31:78 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:32:21:32:21 | f | semmle.label | f |
| tests.go:33:29:33:29 | f | semmle.label | f |
| tests.go:43:5:43:76 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:44:21:44:21 | f | semmle.label | f |
| tests.go:45:29:45:29 | f | semmle.label | f |
| tests.go:53:5:53:42 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:54:21:54:21 | f | semmle.label | f |
| tests.go:55:29:55:29 | f | semmle.label | f |
| tests.go:60:5:60:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:62:3:62:3 | f | semmle.label | f |
| tests.go:70:5:70:42 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:72:3:72:3 | f | semmle.label | f |
| tests.go:108:5:108:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:110:9:110:9 | f | semmle.label | f |
| tests.go:124:5:124:38 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:128:3:128:3 | f | semmle.label | f |
| tests.go:51:5:51:78 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:53:3:53:3 | f | semmle.label | f |
| tests.go:63:5:63:76 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:65:3:65:3 | f | semmle.label | f |
| tests.go:105:5:105:78 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:107:9:107:9 | f | semmle.label | f |
| tests.go:122:5:122:78 | ... := ...[0] | semmle.label | ... := ...[0] |
| tests.go:126:3:126:3 | f | semmle.label | f |
subpaths
#select
| tests.go:22:8:22:8 | f | tests.go:9:2:9:74 | ... := ...[0] | tests.go:22:8:22: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:9:12:9:74 | call to OpenFile | call to OpenFile |
| tests.go:22:8:22:8 | f | tests.go:18:2:18:69 | return statement[0] | tests.go:22:8:22: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:18:9:18:69 | call to OpenFile | call to OpenFile |
| tests.go:27:3:27:3 | f | tests.go:9:2:9:74 | ... := ...[0] | tests.go:27:3:27: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:9:12:9:74 | call to OpenFile | call to OpenFile |
| tests.go:27:3:27:3 | f | tests.go:18:2:18:69 | return statement[0] | tests.go:27:3:27: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:18:9:18:69 | call to OpenFile | call to OpenFile |
| tests.go:62:3:62:3 | f | tests.go:9:2:9:74 | ... := ...[0] | tests.go:62:3:62: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:9:12:9:74 | call to OpenFile | call to OpenFile |
| tests.go:72:3:72:3 | f | tests.go:18:2:18:69 | return statement[0] | tests.go:72:3:72: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:18:9:18:69 | call to OpenFile | call to OpenFile |
| tests.go:110:9:110:9 | f | tests.go:9:2:9:74 | ... := ...[0] | tests.go:110:9:110: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:9:12:9:74 | call to OpenFile | call to OpenFile |
| tests.go:128:3:128:3 | f | tests.go:9:2:9:74 | ... := ...[0] | tests.go:128:3:128: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:9:12:9:74 | call to OpenFile | call to OpenFile |
| tests.go:9:8:9:8 | f | tests.go:31:5:31:78 | ... := ...[0] | tests.go:9:8:9: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:31:15:31:78 | call to OpenFile | call to OpenFile |
| tests.go:9:8:9:8 | f | tests.go:43:5:43:76 | ... := ...[0] | tests.go:9:8:9: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:43:15:43:76 | call to OpenFile | call to OpenFile |
| tests.go:14:3:14:3 | f | tests.go:31:5:31:78 | ... := ...[0] | tests.go:14:3:14: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:31:15:31:78 | call to OpenFile | call to OpenFile |
| tests.go:14:3:14:3 | f | tests.go:43:5:43:76 | ... := ...[0] | tests.go:14:3:14: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:43:15:43:76 | call to OpenFile | call to OpenFile |
| tests.go:53:3:53:3 | f | tests.go:51:5:51:78 | ... := ...[0] | tests.go:53:3:53: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:51:15:51:78 | call to OpenFile | call to OpenFile |
| tests.go:65:3:65:3 | f | tests.go:63:5:63:76 | ... := ...[0] | tests.go:65:3:65: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:63:15:63:76 | call to OpenFile | call to OpenFile |
| tests.go:107:9:107:9 | f | tests.go:105:5:105:78 | ... := ...[0] | tests.go:107:9:107: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:105:15:105:78 | call to OpenFile | call to OpenFile |
| tests.go:126:3:126:3 | f | tests.go:122:5:122:78 | ... := ...[0] | tests.go:126:3:126: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:122:15:122:78 | call to OpenFile | call to OpenFile |

View File

@@ -5,19 +5,6 @@ import (
"os"
)
func openFileWrite(filename string) (*os.File, error) {
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
return f, err
}
func openFileRead(filename string) (*os.File, error) {
return os.OpenFile(filename, os.O_RDONLY|os.O_CREATE, 0666)
}
func openFileReadWrite(filename string) (*os.File, error) {
return os.OpenFile(filename, os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666)
}
func closeFileDeferred(f *os.File) {
defer f.Close() // NOT OK, if `f` is writable
}
@@ -40,41 +27,48 @@ func closeFileDeferredIndirectReturn(f *os.File) {
}
func deferredCalls() {
if f, err := openFileWrite("foo.txt"); err != nil {
// open file for writing
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
closeFileDeferred(f) // NOT OK
closeFileDeferredIndirect(f) // NOT OK
}
if f, err := openFileRead("foo.txt"); err != nil {
// open file for reading
if f, err := os.OpenFile("foo.txt", os.O_RDONLY|os.O_CREATE, 0666); err != nil {
closeFileDeferred(f) // OK
closeFileDeferredIndirect(f) // OK
}
if f, err := openFileReadWrite("foo.txt"); err != nil {
// open file for reading and writing
if f, err := os.OpenFile("foo.txt", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
closeFileDeferred(f) // NOT OK
closeFileDeferredIndirect(f) // NOT OK
}
}
func notDeferred() {
if f, err := openFileWrite("foo.txt"); err != nil {
// open file for writing
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
// the handle is write-only and we don't check if `Close` succeeds
f.Close() // NOT OK
}
if f, err := openFileRead("foo.txt"); err != nil {
// open file for reading
if f, err := os.OpenFile("foo.txt", os.O_RDONLY|os.O_CREATE, 0666); err != nil {
// the handle is read-only, so this is ok
f.Close() // OK
}
if f, err := openFileReadWrite("foo.txt"); err != nil {
// open file for reading and writing
if f, err := os.OpenFile("foo.txt", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
// the handle is read-write and we don't check if `Close` succeeds
f.Close() // NOT OK
}
}
func foo() error {
if f, err := openFileWrite("foo.txt"); err != nil {
// open file for writing
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
// the result of the call to `Close` is returned to the caller
return f.Close() // OK
}
@@ -83,7 +77,8 @@ func foo() error {
}
func isSyncedFirst() {
if f, err := openFileWrite("foo.txt"); err != nil {
// open file for writing
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
// we have a call to `Sync` and check whether it was successful before proceeding
if err := f.Sync(); err != nil {
f.Close() // OK
@@ -93,7 +88,8 @@ func isSyncedFirst() {
}
func deferredCloseWithSync() {
if f, err := openFileWrite("foo.txt"); err != nil {
// 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() // OK
@@ -105,7 +101,8 @@ func deferredCloseWithSync() {
}
func deferredCloseWithSyncEarlyReturn(n int) {
if f, err := openFileWrite("foo.txt"); err != nil {
// 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
defer f.Close() // NOT OK
@@ -121,7 +118,8 @@ func deferredCloseWithSyncEarlyReturn(n int) {
}
func unhandledSync() {
if f, err := openFileWrite("foo.txt"); err != nil {
// open file for writing
if f, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err != nil {
// we have a call to `Sync` which precedes the call to `Close`, but there is no check
// to see if `Sync` may have failed
f.Sync()