CodeQL for Golang Practise(2)
Basic Query for Go code
Key points:
- Practise the query in LGTM
- Sample query
import go // Imports the standard CodeQL libraries for Go.
from Method m, Variable recv, Write w, Field f // Defines the variables for the query.
where
recv = m.getReceiver() and
w.writesField(recv.getARead(), f, _) and
not recv.getType() instanceof PointerType // Defines a condition on the variables.
not exists(ReturnStmt ret | ret.getExpr() = recv.getARead().asExpr()) // Remove false positive results
select w, "This update to " + f + " has no effect, because " + recv + " is not a pointer." // Defines what to report for each match.
Gojenkins on LGTM
In last post the gojenkins repo is clones and analyzed locally, but since it is open source project, so LGTM has already had the results.
Moreover, we can see some errors that has already been identified by the built-in codeql scanner.
And the error is identified by the signature:
To query this project, click the query this project
button, will be redirected to the query console.
Data Flow Analysis
Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used.
Usage:
- Discover insecure ways of data using
- Discover dangerous arguments
- Discover sensitive data leakage
- Understand the program’s behaviour
- Find unintialized variables
- Find resource leaks
Example Queries on LGTM.com
Instead of trying complex queries in the beginning, it is good to read some sample queries and try to understand their meanings.
Call to built-in function
When we try the example queries Call to built-in function
:
import go
from DataFlow::CallNode call
where call = Builtin::len().getACall()
select call
It will shows all the places that using the built-in function len
.
Call to library function
Finds calls to “fmt.Println”.
import go
from Function println, DataFlow::CallNode call
where
println.hasQualifiedName("fmt", "Println") and
call = println.getACall()
select call
Sample Matched result:
fmt.Println(href)
Call to Method
Finds calls to the Get
method of type Header
from the net/http
package.
import go
from Method get, DataFlow::CallNode call
where
get.hasQualifiedName("net/http", "Header", "Get") and
call = get.getACall()
select call
Sample Matched result:
textSize := rsp.Header.Get("X-Text-Size")
Comparison with Nil
import go
from DataFlow::EqualityTestNode eq, DataFlow::Node nd, DataFlow::Node nil
where
nil = Builtin::nil().getARead() and
eq.eq(_, nd, nil)
select eq
Sample Matched result:
if err != nil {
return nil, err
}
Comparison with Zero
import go
from DataFlow::RelationalComparisonNode cmp, DataFlow::Node unsigned, DataFlow::Node zero
where
zero.getNumericValue() = 0 and
unsigned.getType().getUnderlyingType() instanceof UnsignedIntegerType and
cmp.leq(_, zero, unsigned, 0)
select cmp, unsigned
Compile-time Constant
import go
from DataFlow::Node zero
where zero.getNumericValue() = 0
select zero
Field Read
Finds code that reads Request.Method
.
import go
from Field reqm, Read read
where
reqm.hasQualifiedName("net/http", "Request", "Method") and
read = reqm.getARead()
select read
Field Write
Finds assignments to field Status
of type Response
from package net/http
.
import go
from Field status, Write write
where
status.hasQualifiedName("net/http", "Response", "Status") and
write = status.getAWrite()
select write, write.getRhs()
Function
Finds functions called “main”.
import go
from Function main
where main.getName() = "main"
select main
If statements with empty then branch
import go
from IfStmt i
where i.getThen().getNumStmt() = 0
select i
Increment statements in loops
Finds increment statements that are nested in a loop.
import go
from IncStmt s, LoopStmt l
where s.getParent+() = l
select s, l
Parameter
Finds parameters of type “ResponseWriter” from package “net/http”.
import go
from Parameter req
where req.getType().hasQualifiedName("net/http", "ResponseWriter")
select req
Receiver Variable
Finds receiver variables of pointer type.
import go
from ReceiverVariable recv
where recv.getType() instanceof PointerType
select recv
Result variable
Finds result variables of type “error”.
import go
from ResultVariable err
where err.getType() = Builtin::error().getType()
select err
Type
Finds type Request
from package net/http
.
import go
from Type request
where request.hasQualifiedName("net/http", "Request")
select request
Variable
Finds variables called “err”.
import go
from Variable err
where err.getName() = "err"
select err, err.getDeclaration()
Variable Read
Finds code that reads a variable called err
.
import go
from Variable err, Read read
where
err.getName() = "err" and
read = err.getARead()
select read
Variable Write
Finds assignments to variables named “err”.
import go
from Variable err, Write write
where
err.getName() = "err" and
write = err.getAWrite()
select write, write.getRhs()