mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
feat: initial GoMicro modelling
This commit is contained in:
116
go/ql/lib/semmle/go/frameworks/GoMicro.qll
Normal file
116
go/ql/lib/semmle/go/frameworks/GoMicro.qll
Normal file
@@ -0,0 +1,116 @@
|
||||
import go
|
||||
|
||||
module GoMicro {
|
||||
class GoMicroServerType extends Type {
|
||||
GoMicroServerType() { this.hasQualifiedName("go-micro.dev/v4/server", "Server") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A file that is generated by the protobuf compiler.
|
||||
*/
|
||||
class ProtocGeneratedFile extends File {
|
||||
ProtocGeneratedFile() {
|
||||
exists(string prefix, File f |
|
||||
prefix = this.getBaseName().regexpCapture("^(.*)\\.pb(\\.micro)?\\.go$", 1) and
|
||||
this.getParentContainer() = f.getParentContainer()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that is generated by the protobuf compiler.
|
||||
*/
|
||||
class ProtocMessageType extends Type {
|
||||
ProtocMessageType() {
|
||||
exists(TypeEntity te |
|
||||
te.getType() = this and
|
||||
te.getDeclaration().getLocation().getFile() instanceof ProtocGeneratedFile and
|
||||
exists(MethodDecl md |
|
||||
md.getName() = "ProtoMessage" and
|
||||
this = md.getReceiverDecl().getTypeExpr().getAChild().(TypeName).getType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override string getName() { result = this.getUnderlyingType().getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Server internal
|
||||
*/
|
||||
class ServiceInterfaceType extends InterfaceType {
|
||||
NamedType namedType;
|
||||
|
||||
ServiceInterfaceType() {
|
||||
exists(TypeEntity te |
|
||||
te.getType() = namedType and
|
||||
namedType.getUnderlyingType() = this and
|
||||
te.getDeclaration().getLocation().getFile() instanceof ProtocGeneratedFile
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the interface.
|
||||
*/
|
||||
override string getName() { result = namedType.getName() }
|
||||
|
||||
/**
|
||||
* Gets the named type on top of this interface type.
|
||||
*/
|
||||
NamedType getNamedType() { result = namedType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A service server type.
|
||||
*/
|
||||
class ServiceServerType extends NamedType {
|
||||
ServiceServerType() {
|
||||
exists(ServiceInterfaceType i, TypeEntity te |
|
||||
this.implements(i) and
|
||||
this.getName().regexpMatch("(?i).*Handler") and
|
||||
te.getType() = this and
|
||||
te.getDeclaration().getLocation().getFile() instanceof ProtocGeneratedFile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A service register handler.
|
||||
*/
|
||||
class ServiceRegisterHandler extends Function {
|
||||
ServiceRegisterHandler() {
|
||||
exists(ServiceServerType c, GoMicroServerType s |
|
||||
this.getName().regexpMatch("(?i)register" + c.getName()) and
|
||||
this.getParameterType(0) = s and
|
||||
this.getDeclaration().getLocation().getFile() instanceof ProtocGeneratedFile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A service handler.
|
||||
*/
|
||||
class ServiceHandler extends Method {
|
||||
ServiceHandler() {
|
||||
exists(DataFlow::CallNode call, Type handlerType, ServiceInterfaceType i |
|
||||
call.getTarget() instanceof ServiceRegisterHandler and
|
||||
call.getArgument(1).getType() = handlerType and
|
||||
this = handlerType.getMethod(_) and
|
||||
this.implements(i.getNamedType().getMethod(_))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote / Untrusted requests coming to the service handler.
|
||||
*/
|
||||
class Request extends UntrustedFlowSource::Range instanceof DataFlow::ParameterNode {
|
||||
Request() {
|
||||
exists(FuncDef c, ServiceHandler handler | handler.getFuncDecl() = c |
|
||||
this.asParameter().isParameterOf(c, 1) and
|
||||
handler.getParameterType(0).hasQualifiedName("context", "Context") and
|
||||
this.getType().(PointerType).getBaseType() instanceof ProtocMessageType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user