Merge pull request #473 from sauyon/revel

Add models for Revel and HTML templates
This commit is contained in:
Sauyon Lee
2021-03-18 18:21:53 -07:00
committed by GitHub
64 changed files with 3643 additions and 267 deletions

3
.gitattributes vendored
View File

@@ -1,5 +1,6 @@
# Force git not to modify line endings for go files under the ql directory
# Force git not to modify line endings for go or html files under the ql directory
ql/**/*.go -text
ql/**/*.html -text
# Force git not to modify line endings for dbschemes
*.dbscheme -text

View File

@@ -14,7 +14,7 @@ CODEQL_PLATFORM = osx64
endif
endif
CODEQL_TOOLS = $(addprefix codeql-tools/,autobuild.cmd autobuild.sh index.cmd index.sh linux64 osx64 win64)
CODEQL_TOOLS = $(addprefix codeql-tools/,autobuild.cmd autobuild.sh pre-finalize.cmd pre-finalize.sh index.cmd index.sh linux64 osx64 win64)
EXTRACTOR_PACK_OUT = build/codeql-extractor-go

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Support for extracting HTML files has been added, alongside support for Raw Revel templates.

View File

@@ -2,6 +2,7 @@
SETLOCAL EnableDelayedExpansion
type NUL && "%CODEQL_EXTRACTOR_GO_ROOT%/tools/%CODEQL_PLATFORM%/go-extractor.exe" -mod=vendor ./...
type NUL && "%CODEQL_EXTRACTOR_GO_ROOT%/tools/pre-finalize.cmd"
exit /b %ERRORLEVEL%
ENDLOCAL

View File

@@ -8,3 +8,4 @@ if [ "$CODEQL_PLATFORM" != "linux64" ] && [ "$CODEQL_PLATFORM" != "osx64" ] ; th
fi
"$CODEQL_EXTRACTOR_GO_ROOT/tools/$CODEQL_PLATFORM/go-extractor" -mod=vendor ./...
"$CODEQL_EXTRACTOR_GO_ROOT/tools/pre-finalize.sh"

View File

@@ -0,0 +1,19 @@
@echo off
SETLOCAL EnableDelayedExpansion
if NOT "%CODEQL_EXTRACTOR_GO_EXTRACT_HTML%"=="no" (
type NUL && "%CODEQL_DIST%/codeql.exe" database index-files ^
--working-dir=. ^
--include-extension=.htm ^
--include-extension=.html ^
--include-extension=.xhtm ^
--include-extension=.xhtml ^
--include-extension=.vue ^
--size-limit 10m ^
--language html ^
-- ^
"%CODEQL_EXTRACTOR_GO_WIP_DATABASE%" ^
|| echo "HTML extraction failed; continuing"
exit /b %ERRORLEVEL%
)

18
codeql-tools/pre-finalize.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
set -eu
if [ "${CODEQL_EXTRACTOR_GO_EXTRACT_HTML:-yes}" != "no" ]; then
"$CODEQL_DIST/codeql" database index-files \
--working-dir=. \
--include-extension=.htm \
--include-extension=.html \
--include-extension=.xhtm \
--include-extension=.xhtml \
--include-extension=.vue \
--size-limit 10m \
--language html \
-- \
"$CODEQL_EXTRACTOR_GO_WIP_DATABASE" \
|| echo "HTML extraction failed; continuing."
fi

View File

@@ -362,6 +362,15 @@ func NewUnionType(name string, parents ...*UnionType) *UnionType {
return tp
}
// AddChild adds the type with given `name` to the union type.
// This is useful if a type defined in a snippet should be a child of a type defined in Go.
func (parent *UnionType) AddChild(name string) bool {
tp := &PrimaryKeyType{name}
// don't add tp to types; it's expected that it's already in the db somehow.
parent.components = append(parent.components, tp)
return true
}
// NewAliasType constructs a new alias type with the given `name` that aliases `underlying`
func NewAliasType(name string, underlying Type) *AliasType {
tp := &AliasType{name, underlying}

View File

@@ -44,12 +44,91 @@ snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
`)
// Copied directly from the XML dbscheme
var xmlSnippet = AddDefaultSnippet(`
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
`)
// ContainerType is the type of files and folders
var ContainerType = NewUnionType("@container")
// LocatableType is the type of program entities that have locations
var LocatableType = NewUnionType("@locatable")
// Adds xmllocatable as a locatable
var XmlLocatableAsLocatable = LocatableType.AddChild("@xmllocatable")
// NodeType is the type of AST nodes
var NodeType = NewUnionType("@node", LocatableType)

View File

@@ -15,7 +15,22 @@ import go
import semmle.go.security.ReflectedXss::ReflectedXss
import DataFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to $@.",
source.getNode(), "user-provided value"
from
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, string msg, string part,
Locatable partloc
where
cfg.hasFlowPath(source, sink) and
(
exists(string kind | kind = sink.getNode().(SharedXss::Sink).getSinkKind() |
kind = "rawtemplate" and
msg =
"Cross-site scripting vulnerability due to $@. This template argument is instantiated raw $@." and
part = "here"
)
or
not exists(sink.getNode().(SharedXss::Sink).getSinkKind()) and
msg = "Cross-site scripting vulnerability due to $@." and
part = ""
) and
partloc = sink.getNode().(SharedXss::Sink).getAssociatedLoc()
select sink.getNode(), source, sink, msg, source.getNode(), "user-provided value", partloc, part

View File

@@ -36,6 +36,80 @@ snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
@@ -133,7 +207,7 @@ has_ellipsis(int id: @callorconversionexpr ref);
@container = @file | @folder;
@locatable = @node | @localscope;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;

View File

@@ -12,6 +12,7 @@ import semmle.go.Errors
import semmle.go.Expr
import semmle.go.Files
import semmle.go.GoMod
import semmle.go.HTML
import semmle.go.Locations
import semmle.go.Packages
import semmle.go.Scopes
@@ -19,6 +20,7 @@ import semmle.go.Stmt
import semmle.go.StringOps
import semmle.go.Types
import semmle.go.Util
import semmle.go.VariableWithFields
import semmle.go.concepts.HTTP
import semmle.go.controlflow.BasicBlocks
import semmle.go.controlflow.ControlFlowGraph

214
ql/src/semmle/go/HTML.qll Normal file
View File

@@ -0,0 +1,214 @@
/** Provides classes for working with HTML documents. */
import go
module HTML {
/**
* An HTML file.
*/
class HtmlFile extends File {
HtmlFile() { this.getExtension().regexpMatch("x?html?") }
}
/**
* An HTML element.
*
* Example:
*
* ```
* <a href="semmle.com">Semmle</a>
* ```
*/
class Element extends Locatable, @xmlelement {
Element() { exists(HtmlFile f | xmlElements(this, _, _, _, f)) }
override Location getLocation() { xmllocations(this, result) }
/**
* Gets the name of this HTML element.
*
* For example, the name of `<br>` is `br`.
*/
string getName() { xmlElements(this, result, _, _, _) }
/**
* Gets the parent element of this element, if any.
*/
Element getParent() { xmlElements(this, _, result, _, _) }
/**
* Holds if this is a toplevel element, that is, if it does not have a parent element.
*/
predicate isTopLevel() { not exists(getParent()) }
/**
* Gets the root HTML document element in which this element is contained.
*/
DocumentElement getDocument() { result = getRoot() }
/**
* Gets the root element in which this element is contained.
*/
Element getRoot() { if isTopLevel() then result = this else result = getParent().getRoot() }
/**
* Gets the `i`th child element (0-based) of this element.
*/
Element getChild(int i) { xmlElements(result, _, this, i, _) }
/**
* Gets a child element of this element.
*/
Element getChild() { result = getChild(_) }
/**
* Gets the `i`th attribute (0-based) of this element.
*/
Attribute getAttribute(int i) { xmlAttrs(result, this, _, _, i, _) }
/**
* Gets an attribute of this element.
*/
Attribute getAnAttribute() { result = getAttribute(_) }
/**
* Gets an attribute of this element that has the given name.
*/
Attribute getAttributeByName(string name) {
result = getAnAttribute() and
result.getName() = name
}
/**
* Gets the text node associated with this element.
*/
TextNode getTextNode() { result.getParent() = this }
override string toString() { result = "<" + getName() + ">...</>" }
}
/**
* An attribute of an HTML element.
*
* Examples:
*
* ```
* <a
* href ="semmle.com" <!-- an attribute -->
* target=_blank <!-- also an attribute -->
* >Semmle</a>
* ```
*/
class Attribute extends Locatable, @xmlattribute {
Attribute() { xmlAttrs(this, _, _, _, _, any(HtmlFile f)) }
override Location getLocation() { xmllocations(this, result) }
/**
* Gets the element to which this attribute belongs.
*/
Element getElement() { xmlAttrs(this, result, _, _, _, _) }
/**
* Gets the root element in which the element to which this attribute
* belongs is contained.
*/
Element getRoot() { result = getElement().getRoot() }
/**
* Gets the name of this attribute.
*/
string getName() { xmlAttrs(this, _, result, _, _, _) }
/**
* Gets the value of this attribute.
*
* For attributes without an explicitly specified value, the
* result is the empty string.
*/
string getValue() { xmlAttrs(this, _, _, result, _, _) }
override string toString() { result = getName() + "=" + getValue() }
}
/**
* An HTML `<html>` element.
*
* Example:
*
* ```
* <html>
* <body>
* This is a test.
* </body>
* </html>
* ```
*/
class DocumentElement extends Element {
DocumentElement() { getName() = "html" }
}
/**
* An HTML text node.
*
* Example:
*
* ```
* <div>
* This text is represented as a text node.
* </div>
* ```
*/
class TextNode extends Locatable, @xmlcharacters {
TextNode() { exists(HtmlFile f | xmlChars(this, _, _, _, _, f)) }
override string toString() { result = getText() }
/**
* Gets the content of this text node.
*
* Note that entity expansion has been performed already.
*/
string getText() { xmlChars(this, result, _, _, _, _) }
/**
* Gets the parent this text.
*/
Element getParent() { xmlChars(this, _, result, _, _, _) }
/**
* Gets the child index number of this text node.
*/
int getIndex() { xmlChars(this, _, _, result, _, _) }
/**
* Holds if this text node is inside a `CDATA` tag.
*/
predicate isCData() { xmlChars(this, _, _, _, 1, _) }
override Location getLocation() { xmllocations(this, result) }
}
/**
* An HTML comment.
*
* Example:
*
* ```
* <!-- this is a comment -->
* ```
*/
class CommentNode extends Locatable, @xmlcomment {
CommentNode() { exists(HtmlFile f | xmlComments(this, _, _, f)) }
/** Gets the element in which this comment occurs. */
Element getParent() { xmlComments(this, _, result, _) }
/** Gets the text of this comment, not including delimiters. */
string getText() { result = toString().regexpCapture("(?s)<!--(.*)-->", 1) }
override string toString() { xmlComments(this, result, _, _) }
override Location getLocation() { xmllocations(this, result) }
}
}

View File

@@ -0,0 +1,198 @@
/** Provides the `VariableWithFields` class, for working with variables with a chain of field or element accesses chained to it. */
import go
private newtype TVariableWithFields =
TVariableRoot(Variable v) or
TVariableFieldStep(VariableWithFields base, Field f) {
exists(fieldAccessPathAux(base, f)) or exists(fieldWriteAccessPathAux(base, f))
} or
TVariableElementStep(VariableWithFields base, string e) {
exists(elementAccessPathAux(base, e)) or exists(elementWriteAccessPathAux(base, e))
}
/**
* Gets a representation of the write target `wt` as a variable with fields value if there is one.
*/
private TVariableWithFields writeAccessPath(IR::WriteTarget wt) {
exists(Variable v | wt = v.getAWrite().getLhs() | result = TVariableRoot(v))
or
exists(VariableWithFields base, Field f | wt = fieldWriteAccessPathAux(base, f) |
result = TVariableFieldStep(base, f)
)
or
exists(VariableWithFields base, string e | wt = elementWriteAccessPathAux(base, e) |
result = TVariableElementStep(base, e)
)
}
/**
* Gets a representation of `insn` as a variable with fields value if there is one.
*/
private TVariableWithFields accessPath(IR::Instruction insn) {
exists(Variable v | insn = v.getARead().asInstruction() | result = TVariableRoot(v))
or
exists(VariableWithFields base, Field f | insn = fieldAccessPathAux(base, f) |
result = TVariableFieldStep(base, f)
)
or
exists(VariableWithFields base, string e | insn = elementAccessPathAux(base, e) |
result = TVariableElementStep(base, e)
)
}
/**
* Gets an IR instruction that reads a field `f` from a node that is represented
* by variable with fields value `base`.
*/
private IR::Instruction fieldAccessPathAux(TVariableWithFields base, Field f) {
exists(IR::FieldReadInstruction fr, IR::EvalInstruction frb |
fr.getBase() = frb or
fr.getBase() = IR::implicitDerefInstruction(frb.getExpr())
|
base = accessPath(frb) and
f = fr.getField() and
result = fr
)
}
/**
* Gets an IR write target that represents a field `f` from a node that is represented
* by variable with fields value `base`.
*/
private IR::WriteTarget fieldWriteAccessPathAux(TVariableWithFields base, Field f) {
exists(IR::FieldTarget ft, IR::EvalInstruction ftb |
ft.getBase() = ftb or
ft.getBase() = IR::implicitDerefInstruction(ftb.getExpr())
|
base = accessPath(ftb) and
ft.getField() = f and
result = ft
)
}
/**
* Gets an IR instruction that reads an element `e` from a node that is represented
* by variable with fields value `base`.
*/
private IR::Instruction elementAccessPathAux(TVariableWithFields base, string e) {
exists(IR::ElementReadInstruction er, IR::EvalInstruction erb |
er.getBase() = erb or
er.getBase() = IR::implicitDerefInstruction(erb.getExpr())
|
base = accessPath(erb) and
e = er.getIndex().getExactValue() and
result = er
)
}
/**
* Gets an IR write target that represents an element `e` from a node that is represented
* by variable with fields value `base`.
*/
private IR::WriteTarget elementWriteAccessPathAux(TVariableWithFields base, string e) {
exists(IR::ElementTarget et, IR::EvalInstruction etb |
et.getBase() = etb or
et.getBase() = IR::implicitDerefInstruction(etb.getExpr())
|
base = accessPath(etb) and
e = et.getIndex().getExactValue() and
result = et
)
}
/** A variable with zero or more fields or elements read from it. */
class VariableWithFields extends TVariableWithFields {
/**
* Gets the variable corresponding to the base of this variable with fields.
*
* For example, the variable corresponding to `a` for the variable with fields
* corresponding to `a.b[c]`.
*/
Variable getBaseVariable() { this.getParent*() = TVariableRoot(result) }
/**
* Gets the variable with fields corresponding to the parent of this variable with fields.
*
* For example, the variable with fields corresponding to `a.b` for the variable with fields
* corresponding to `a.b[c]`.
*/
VariableWithFields getParent() {
exists(VariableWithFields base |
this = TVariableFieldStep(base, _) or this = TVariableElementStep(base, _)
|
result = base
)
}
/** Gets a use that refers to this variable with fields. */
DataFlow::Node getAUse() { this = accessPath(result.asInstruction()) }
/** Gets the type of this variable with fields. */
Type getType() {
exists(IR::Instruction acc | this = accessPath(acc) | result = acc.getResultType())
}
/** Gets a textual representation of this element. */
string toString() {
exists(Variable var | this = TVariableRoot(var) | result = "(" + var + ")")
or
exists(VariableWithFields base, Field f | this = TVariableFieldStep(base, f) |
result = base + "." + f.getName()
)
or
exists(VariableWithFields base, string e | this = TVariableElementStep(base, e) |
result = base + "[" + e + "]"
)
}
/**
* Gets the qualified name of the source variable or variable and fields that this represents.
*
* For example, for the variable with fields that represents the field `a.b[c]`, this would get the string
* `"a.b.c"`.
*/
string getQualifiedName() {
exists(Variable v | this = TVariableRoot(v) | result = v.getName())
or
exists(VariableWithFields base, Field f | this = TVariableFieldStep(base, f) |
result = base.getQualifiedName() + "." + f.getName()
)
or
exists(VariableWithFields base, string e | this = TVariableElementStep(base, e) |
result = base.getQualifiedName() + "." + e.replaceAll(".", "\\.")
)
}
/**
* Gets a write of this variable with fields.
*/
Write getAWrite() { this = writeAccessPath(result.getLhs()) }
/**
* Gets the field that is the last step of this variable with fields, if any.
*
* For example, the field `c` for the variable with fields `a.b.c`.
*/
Field getField() { this = TVariableFieldStep(_, result) }
/**
* Gets the element that this variable with fields reads, if any.
*
* For example, the string value of `c` for the variable with fields `a.b[c]`.
*/
string getElement() { this = TVariableElementStep(_, result) }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.getBaseVariable().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}

View File

@@ -223,6 +223,35 @@ module HTTP {
DataFlow::Node getAContentTypeNode() { result = self.getAContentTypeNode() }
}
/** Provides a class for modeling new HTTP template response-body APIs. */
module TemplateResponseBody {
/**
* An expression which is written to an HTTP response body via a template execution.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `HTTP::ResponseBody` instead.
*/
abstract class Range extends ResponseBody::Range {
/** Gets the read of the variable inside the template where this value is read. */
abstract HtmlTemplate::TemplateRead getRead();
}
}
/**
* An expression which is written to an HTTP response body via a template execution.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `HTTP::TemplateResponseBody::Range` instead.
*/
class TemplateResponseBody extends ResponseBody {
override TemplateResponseBody::Range self;
TemplateResponseBody() { this = self }
/** Gets the read of the variable inside the template where this value is read. */
HtmlTemplate::TemplateRead getRead() { result = self.getRead() }
}
/** Provides a class for modeling new HTTP client request APIs. */
module ClientRequest {
/**

View File

@@ -104,8 +104,7 @@ module Revel {
* Note these don't actually generate the response, they return a struct which is then returned by the controller
* method, but it is very likely if a string is being rendered that it will end up sent to the user.
*
* The `Render` and `RenderTemplate` methods are excluded for now because both execute HTML templates, and deciding
* whether a particular value is exposed unescaped or not requires parsing the template.
* The `Render` and `RenderTemplate` methods are handled by `TemplateRender` below.
*
* The `RenderError` method can actually return HTML content, but again only via an HTML template if one exists;
* we assume it falls back to return plain text as this implies there is probably not an injection opportunity
@@ -216,4 +215,114 @@ module Revel {
inp = input and outp = output
}
}
/**
* A read in a Revel template that uses Revel's `raw` function.
*/
class RawTemplateRead extends HtmlTemplate::TemplateRead {
RawTemplateRead() { parent.getBody().regexpMatch("(?s)raw\\s.*") }
}
/**
* A write to a template argument field that is read raw inside of a template.
*/
private class RawTemplateArgument extends HTTP::TemplateResponseBody::Range {
RawTemplateRead read;
RawTemplateArgument() {
exists(TemplateRender render, VariableWithFields var |
render.getRenderedFile() = read.getFile() and
// if var is a.b.c, any rhs of a write to a, a.b, or a.b.cb
this = var.getParent*().getAWrite().getRhs()
|
var.getParent*() = render.getArgumentVariable() and
(
var = read.getReadVariable(render.getArgumentVariable())
or
// if no write or use of that variable exists, no VariableWithFields will be generated
// so we try to find a parent VariableWithFields
// this isn't covered by the 'getParent*' above because no match would be found at all
// for var
not exists(read.getReadVariable(render.getArgumentVariable())) and
exists(string fieldName | fieldName = read.getFieldName() |
var.getQualifiedName() =
render.getArgumentVariable().getQualifiedName() +
["." + fieldName.substring(0, fieldName.indexOf(".")), ""]
)
)
or
// a revel controller.Render(arg) will set controller.ViewArgs["arg"] = arg
exists(Variable arg | arg.getARead() = render.(ControllerRender).getAnArgument() |
var.getBaseVariable() = arg and
var.getQualifiedName() = read.getFieldName()
)
)
}
override string getAContentType() { result = "text/html" }
override HTTP::ResponseWriter getResponseWriter() { none() }
override HtmlTemplate::TemplateRead getRead() { result = read }
}
/**
* A render of a template.
*/
abstract class TemplateRender extends DataFlow::Node, TemplateInstantiation::Range {
/** Gets the name of the file that is rendered. */
abstract File getRenderedFile();
/** Gets the variable passed as an argument to the template. */
abstract VariableWithFields getArgumentVariable();
override DataFlow::Node getADataArgument() { result = this.getArgumentVariable().getAUse() }
}
/** A call to `Controller.Render`. */
private class ControllerRender extends TemplateRender, DataFlow::MethodCallNode {
ControllerRender() { this.getTarget().hasQualifiedName(packagePath(), "Controller", "Render") }
override DataFlow::Node getTemplateArgument() { none() }
override File getRenderedFile() {
exists(string controllerRe, string handlerRe, string pathRe |
controllerRe = "\\Q" + this.getReceiver().getType().getName() + "\\E" and
handlerRe = "\\Q" + this.getEnclosingCallable().getName() + "\\E" and
// find a file named '/views/<controller>/<handler>(.<template type>).html
pathRe = "/views/" + controllerRe + "/" + handlerRe + "(\\..*)?\\.html?"
|
result.getAbsolutePath().regexpMatch("(?i).*" + pathRe)
)
}
override VariableWithFields getArgumentVariable() {
exists(VariableWithFields base | base.getAUse().getASuccessor*() = this.getReceiver() |
result.getParent() = base and
result.getField().getName() = "ViewArgs"
)
}
}
/** A call to `Controller.RenderTemplate`. */
private class ControllerRenderTemplate extends TemplateRender, DataFlow::MethodCallNode {
ControllerRenderTemplate() {
this.getTarget().hasQualifiedName(packagePath(), "Controller", "RenderTemplate")
}
override DataFlow::Node getTemplateArgument() { result = this.getArgument(0) }
override File getRenderedFile() {
exists(string pathRe | pathRe = "\\Q" + this.getTemplateArgument().getStringValue() + "\\E" |
result.getAbsolutePath().regexpMatch(".*/" + pathRe)
)
}
override VariableWithFields getArgumentVariable() {
exists(VariableWithFields base | base.getAUse().getASuccessor*() = this.getReceiver() |
result.getParent() = base and
result.getField().getName() = "ViewArgs"
)
}
}
}

View File

@@ -62,4 +62,111 @@ module HtmlTemplate {
input = inp and output = outp
}
}
private class MethodModels extends TaintTracking::FunctionModel, Method {
FunctionInput inp;
FunctionOutput outp;
MethodModels() {
// signature: func (*Template).Execute(wr io.Writer, data interface{}) error
hasQualifiedName("html/template", "Template", "Execute") and
(inp.isParameter(1) and outp.isParameter(0))
or
// signature: func (*Template).ExecuteTemplate(wr io.Writer, name string, data interface{}) error
hasQualifiedName("html/template", "Template", "ExecuteTemplate") and
(inp.isParameter(2) and outp.isParameter(0))
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
private newtype TTemplateStmt =
MkTemplateStmt(HTML::TextNode parent, int idx, string text) {
text = parent.getText().regexpFind("(?s)\\{\\{.*?\\}\\}", idx, _)
}
/**
* A statement inside an HTML template.
*/
class TemplateStmt extends TTemplateStmt {
HTML::TextNode parent;
string text;
TemplateStmt() { this = MkTemplateStmt(parent, _, text) }
/** Gets the text of the body of the template statement. */
string getBody() { result = text.regexpCapture("(?s)\\{\\{(.*)\\}\\}", 1) } // matches the inside of the curly bracket delimiters
/** Gets the file in which this statement appears. */
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
/** Gets a textual representation of this statement. */
string toString() { result = "HTML template statement" }
/** Get the HTML element that contains this template statement. */
HTML::TextNode getEnclosingTextNode() { result = parent }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
parent.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
private newtype TTemplateRead =
MkTemplateRead(TemplateStmt parent, int idx, string text) {
// matches (.<valid golang ident>)*
text = parent.getBody().regexpFind("(\\s|^)\\.(\\p{L}|\\p{N}|\\.)*\\b", idx, _)
}
/**
* A read in an HTML template statement.
*/
class TemplateRead extends TTemplateRead {
TemplateStmt parent;
string text;
TemplateRead() { this = MkTemplateRead(parent, _, text) }
/** Gets the name of the field being read. This may include dots if nested fields are used. */
string getFieldName() { result = text.trim().suffix(1) }
/** Gets the variable with fields that is read if `arg` is passed to this template execution. */
VariableWithFields getReadVariable(VariableWithFields arg) {
if this.getFieldName() = ""
then result = arg
else result.getQualifiedName() = arg.getQualifiedName() + "." + this.getFieldName()
}
/** Gets the file in which this read appears. */
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
/** Gets a textual representation of this statement. */
string toString() { result = "HTML template read of " + text }
/** Get the HTML element that contains this template read. */
HTML::TextNode getEnclosingTextNode() { result = parent.getEnclosingTextNode() }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
parent.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
}

View File

@@ -18,6 +18,14 @@ module SharedXss {
* that do not allow script injection, but injection of other undesirable HTML elements.
*/
string getVulnerabilityKind() { result = "Cross-site scripting" }
/**
* Gets the kind of sink
*/
string getSinkKind() { none() }
/** Gets an associated locatable, if any. */
Locatable getAssociatedLoc() { result = this.getFile() }
}
/** A sanitizer for XSS vulnerabilities. */
@@ -38,6 +46,15 @@ module SharedXss {
HttpResponseBodySink() { not nonHtmlContentType(this) }
}
/**
* An expression that is rendered as part of a template.
*/
class RawTemplateInstantiationSink extends HttpResponseBodySink, HTTP::TemplateResponseBody {
override string getSinkKind() { result = "rawtemplate" }
override Locatable getAssociatedLoc() { result = this.getRead().getEnclosingTextNode() }
}
/**
* Holds if `body` may send a response with a content type other than HTML.
*/

144
ql/src/xml.dbscheme Normal file
View File

@@ -0,0 +1,144 @@
/*
* External artifacts
*/
externalData(
int id : @externalDataElement,
string path : string ref,
int column: int ref,
string value : string ref
);
snapshotDate(
unique date snapshotDate : date ref
);
sourceLocationPrefix(
string prefix : string ref
);
/*
* Locations and files
*/
@location = @location_default ;
@locatable = @xmllocatable ;
locations_default(
unique int id: @location_default,
int file: @file ref,
int beginLine: int ref,
int beginColumn: int ref,
int endLine: int ref,
int endColumn: int ref
);
hasLocation(
int locatableid: @locatable ref,
int id: @location ref
);
@sourceline = @locatable ;
#keyset[element_id]
numlines(
int element_id: @sourceline ref,
int num_lines: int ref,
int num_code: int ref,
int num_comment: int ref
);
files(
unique int id: @file,
string name: string ref,
string simple: string ref,
string ext: string ref,
int fromSource: int ref // deprecated
);
folders(
unique int id: @folder,
string name: string ref,
string simple: string ref
);
@container = @folder | @file
containerparent(
int parent: @container ref,
unique int child: @container ref
);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;

View File

@@ -0,0 +1,4 @@
| test.html:2:1:2:23 | <h1>...</> |
| test.html:3:1:11:5 | <ul>...</> |
| test.html:6:13:6:44 | <li>...</> |
| test.html:8:13:8:31 | <li>...</> |

View File

@@ -0,0 +1,3 @@
import go
select any(HTML::Element e)

View File

@@ -0,0 +1 @@
package main

View File

@@ -0,0 +1,11 @@
<!-- HTML fragment for testing extraction of Go templates -->
<h1>{{.PageTitle}}</h1>
<ul>
{{range .Todos}}
{{if .Done}}
<li class="done">{{.Title}}</li>
{{else}}
<li>{{.Title}}</li>
{{end}}
{{end}}
</ul>

View File

@@ -190,56 +190,56 @@ nodes
| test.go:304:21:304:48 | type assertion | semmle.label | type assertion |
| test.go:305:21:305:52 | type assertion | semmle.label | type assertion |
#select
| test.go:28:13:28:30 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:28:13:28:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value |
| test.go:29:13:29:27 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:29:13:29:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value |
| test.go:30:13:30:29 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:30:13:30:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value |
| test.go:35:13:35:43 | type conversion | test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:35:20:35:42 | call to Cookie | user-provided value |
| test.go:40:13:40:52 | type conversion | test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:40:20:40:31 | call to Data | user-provided value |
| test.go:45:13:45:53 | type conversion | test.go:45:20:45:43 | call to GetData : interface type | test.go:45:13:45:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:45:20:45:43 | call to GetData | user-provided value |
| test.go:50:13:50:43 | type conversion | test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:50:20:50:42 | call to Header | user-provided value |
| test.go:55:13:55:42 | type conversion | test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:55:20:55:41 | call to Param | user-provided value |
| test.go:60:13:60:45 | type conversion | test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:60:20:60:33 | call to Params | user-provided value |
| test.go:65:13:65:42 | type conversion | test.go:65:20:65:41 | call to Query : string | test.go:65:13:65:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:65:20:65:41 | call to Query | user-provided value |
| test.go:70:13:70:33 | type conversion | test.go:70:20:70:32 | call to Refer : string | test.go:70:13:70:33 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:70:20:70:32 | call to Refer | user-provided value |
| test.go:75:13:75:35 | type conversion | test.go:75:20:75:34 | call to Referer : string | test.go:75:13:75:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:75:20:75:34 | call to Referer | user-provided value |
| test.go:80:13:80:31 | type conversion | test.go:80:20:80:30 | call to URI : string | test.go:80:13:80:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:80:20:80:30 | call to URI | user-provided value |
| test.go:85:13:85:31 | type conversion | test.go:85:20:85:30 | call to URL : string | test.go:85:13:85:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:85:20:85:30 | call to URL | user-provided value |
| test.go:90:13:90:37 | type conversion | test.go:90:20:90:36 | call to UserAgent : string | test.go:90:13:90:37 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:90:20:90:36 | call to UserAgent | user-provided value |
| test.go:95:14:95:45 | type assertion | test.go:95:14:95:25 | call to Data : map type | test.go:95:14:95:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:95:14:95:25 | call to Data | user-provided value |
| test.go:107:14:107:45 | type assertion | test.go:107:14:107:25 | call to Data : map type | test.go:107:14:107:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:107:14:107:25 | call to Data | user-provided value |
| test.go:119:14:119:45 | type assertion | test.go:119:14:119:25 | call to Data : map type | test.go:119:14:119:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:119:14:119:25 | call to Data | user-provided value |
| test.go:136:23:136:62 | type assertion | test.go:136:23:136:42 | call to Data : map type | test.go:136:23:136:62 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:136:23:136:42 | call to Data | user-provided value |
| test.go:193:14:193:55 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:193:14:193:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value |
| test.go:194:14:194:58 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:194:14:194:58 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value |
| test.go:196:14:196:28 | type assertion | test.go:192:15:192:26 | call to Data : map type | test.go:196:14:196:28 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value |
| test.go:197:14:197:55 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:197:14:197:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value |
| test.go:198:14:198:59 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:198:14:198:59 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value |
| test.go:202:14:202:28 | type conversion | test.go:201:18:201:33 | selection of Form : Values | test.go:202:14:202:28 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:201:18:201:33 | selection of Form | user-provided value |
| test.go:217:14:217:32 | type conversion | test.go:216:2:216:34 | ... := ...[1] : pointer type | test.go:217:14:217:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:216:2:216:34 | ... := ...[1] | user-provided value |
| test.go:219:14:219:20 | content | test.go:216:2:216:34 | ... := ...[0] : File | test.go:219:14:219:20 | content | Cross-site scripting vulnerability due to $@. | test.go:216:2:216:34 | ... := ...[0] | user-provided value |
| test.go:222:14:222:38 | type conversion | test.go:221:2:221:40 | ... := ...[0] : slice type | test.go:222:14:222:38 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:221:2:221:40 | ... := ...[0] | user-provided value |
| test.go:225:14:225:22 | type conversion | test.go:224:7:224:28 | call to GetString : string | test.go:225:14:225:22 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:224:7:224:28 | call to GetString | user-provided value |
| test.go:228:14:228:26 | type conversion | test.go:227:8:227:35 | call to GetStrings : slice type | test.go:228:14:228:26 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:227:8:227:35 | call to GetStrings | user-provided value |
| test.go:231:14:231:27 | type conversion | test.go:230:9:230:17 | call to Input : Values | test.go:231:14:231:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:230:9:230:17 | call to Input | user-provided value |
| test.go:235:14:235:30 | type conversion | test.go:233:6:233:8 | definition of str : myStruct | test.go:235:14:235:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:233:6:233:8 | definition of str | user-provided value |
| test.go:242:21:242:29 | untrusted | test.go:239:15:239:36 | call to GetString : string | test.go:242:21:242:29 | untrusted | Cross-site scripting vulnerability due to $@. | test.go:239:15:239:36 | call to GetString | user-provided value |
| test.go:252:16:252:45 | type conversion | test.go:252:23:252:44 | call to GetCookie : string | test.go:252:16:252:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:252:23:252:44 | call to GetCookie | user-provided value |
| test.go:257:16:257:37 | call to GetCookie | test.go:257:16:257:37 | call to GetCookie | test.go:257:16:257:37 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:257:16:257:37 | call to GetCookie | user-provided value |
| test.go:258:15:258:41 | call to GetCookie | test.go:258:15:258:41 | call to GetCookie | test.go:258:15:258:41 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:258:15:258:41 | call to GetCookie | user-provided value |
| test.go:263:55:263:84 | type conversion | test.go:263:62:263:83 | call to GetCookie : string | test.go:263:55:263:84 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:263:62:263:83 | call to GetCookie | user-provided value |
| test.go:276:21:276:61 | call to GetDisplayString | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:276:21:276:61 | call to GetDisplayString | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:277:21:277:92 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:277:21:277:92 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:278:21:278:96 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:278:21:278:96 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:283:3:285:80 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:283:3:285:80 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:286:21:286:101 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:286:21:286:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:287:21:287:101 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:287:21:287:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:288:21:288:97 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:288:21:288:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:289:21:289:97 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:289:21:289:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:290:21:290:102 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:290:21:290:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:291:21:291:102 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:291:21:291:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:292:21:292:82 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:292:21:292:82 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:294:21:294:133 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:294:21:294:133 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:295:21:295:88 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:295:21:295:88 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:296:21:296:87 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:296:21:296:87 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value |
| test.go:304:21:304:48 | type assertion | test.go:302:15:302:36 | call to GetString : string | test.go:304:21:304:48 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:302:15:302:36 | call to GetString | user-provided value |
| test.go:305:21:305:52 | type assertion | test.go:302:15:302:36 | call to GetString : string | test.go:305:21:305:52 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:302:15:302:36 | call to GetString | user-provided value |
| test.go:28:13:28:30 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:28:13:28:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:29:13:29:27 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:29:13:29:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:30:13:30:29 | type conversion | test.go:26:6:26:10 | definition of bound : bindMe | test.go:30:13:30:29 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:26:6:26:10 | definition of bound | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:35:13:35:43 | type conversion | test.go:35:20:35:42 | call to Cookie : string | test.go:35:13:35:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:35:20:35:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:40:13:40:52 | type conversion | test.go:40:20:40:31 | call to Data : map type | test.go:40:13:40:52 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:40:20:40:31 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:45:13:45:53 | type conversion | test.go:45:20:45:43 | call to GetData : interface type | test.go:45:13:45:53 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:45:20:45:43 | call to GetData | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:50:13:50:43 | type conversion | test.go:50:20:50:42 | call to Header : string | test.go:50:13:50:43 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:50:20:50:42 | call to Header | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:55:13:55:42 | type conversion | test.go:55:20:55:41 | call to Param : string | test.go:55:13:55:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:55:20:55:41 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:60:13:60:45 | type conversion | test.go:60:20:60:33 | call to Params : map type | test.go:60:13:60:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:60:20:60:33 | call to Params | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:65:13:65:42 | type conversion | test.go:65:20:65:41 | call to Query : string | test.go:65:13:65:42 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:65:20:65:41 | call to Query | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:70:13:70:33 | type conversion | test.go:70:20:70:32 | call to Refer : string | test.go:70:13:70:33 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:70:20:70:32 | call to Refer | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:75:13:75:35 | type conversion | test.go:75:20:75:34 | call to Referer : string | test.go:75:13:75:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:75:20:75:34 | call to Referer | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:80:13:80:31 | type conversion | test.go:80:20:80:30 | call to URI : string | test.go:80:13:80:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:80:20:80:30 | call to URI | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:85:13:85:31 | type conversion | test.go:85:20:85:30 | call to URL : string | test.go:85:13:85:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:85:20:85:30 | call to URL | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:90:13:90:37 | type conversion | test.go:90:20:90:36 | call to UserAgent : string | test.go:90:13:90:37 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:90:20:90:36 | call to UserAgent | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:95:14:95:45 | type assertion | test.go:95:14:95:25 | call to Data : map type | test.go:95:14:95:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:95:14:95:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:107:14:107:45 | type assertion | test.go:107:14:107:25 | call to Data : map type | test.go:107:14:107:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:107:14:107:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:119:14:119:45 | type assertion | test.go:119:14:119:25 | call to Data : map type | test.go:119:14:119:45 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:119:14:119:25 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:136:23:136:62 | type assertion | test.go:136:23:136:42 | call to Data : map type | test.go:136:23:136:62 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:136:23:136:42 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:193:14:193:55 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:193:14:193:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:194:14:194:58 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:194:14:194:58 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:196:14:196:28 | type assertion | test.go:192:15:192:26 | call to Data : map type | test.go:196:14:196:28 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:197:14:197:55 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:197:14:197:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:198:14:198:59 | type conversion | test.go:192:15:192:26 | call to Data : map type | test.go:198:14:198:59 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:192:15:192:26 | call to Data | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:202:14:202:28 | type conversion | test.go:201:18:201:33 | selection of Form : Values | test.go:202:14:202:28 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:201:18:201:33 | selection of Form | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:217:14:217:32 | type conversion | test.go:216:2:216:34 | ... := ...[1] : pointer type | test.go:217:14:217:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:216:2:216:34 | ... := ...[1] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:219:14:219:20 | content | test.go:216:2:216:34 | ... := ...[0] : File | test.go:219:14:219:20 | content | Cross-site scripting vulnerability due to $@. | test.go:216:2:216:34 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:222:14:222:38 | type conversion | test.go:221:2:221:40 | ... := ...[0] : slice type | test.go:222:14:222:38 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:221:2:221:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:225:14:225:22 | type conversion | test.go:224:7:224:28 | call to GetString : string | test.go:225:14:225:22 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:224:7:224:28 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:228:14:228:26 | type conversion | test.go:227:8:227:35 | call to GetStrings : slice type | test.go:228:14:228:26 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:227:8:227:35 | call to GetStrings | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:231:14:231:27 | type conversion | test.go:230:9:230:17 | call to Input : Values | test.go:231:14:231:27 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:230:9:230:17 | call to Input | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:235:14:235:30 | type conversion | test.go:233:6:233:8 | definition of str : myStruct | test.go:235:14:235:30 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:233:6:233:8 | definition of str | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:242:21:242:29 | untrusted | test.go:239:15:239:36 | call to GetString : string | test.go:242:21:242:29 | untrusted | Cross-site scripting vulnerability due to $@. | test.go:239:15:239:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:252:16:252:45 | type conversion | test.go:252:23:252:44 | call to GetCookie : string | test.go:252:16:252:45 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:252:23:252:44 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:257:16:257:37 | call to GetCookie | test.go:257:16:257:37 | call to GetCookie | test.go:257:16:257:37 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:257:16:257:37 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:258:15:258:41 | call to GetCookie | test.go:258:15:258:41 | call to GetCookie | test.go:258:15:258:41 | call to GetCookie | Cross-site scripting vulnerability due to $@. | test.go:258:15:258:41 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:263:55:263:84 | type conversion | test.go:263:62:263:83 | call to GetCookie : string | test.go:263:55:263:84 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:263:62:263:83 | call to GetCookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:276:21:276:61 | call to GetDisplayString | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:276:21:276:61 | call to GetDisplayString | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:277:21:277:92 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:277:21:277:92 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:278:21:278:96 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:278:21:278:96 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:283:3:285:80 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:283:3:285:80 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:286:21:286:101 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:286:21:286:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:287:21:287:101 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:287:21:287:101 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:288:21:288:97 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:288:21:288:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:289:21:289:97 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:289:21:289:97 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:290:21:290:102 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:290:21:290:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:291:21:291:102 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:291:21:291:102 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:292:21:292:82 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:292:21:292:82 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:294:21:294:133 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:294:21:294:133 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:295:21:295:88 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:295:21:295:88 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:296:21:296:87 | selection of Filename | test.go:268:2:268:40 | ... := ...[0] : slice type | test.go:296:21:296:87 | selection of Filename | Cross-site scripting vulnerability due to $@. | test.go:268:2:268:40 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:304:21:304:48 | type assertion | test.go:302:15:302:36 | call to GetString : string | test.go:304:21:304:48 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:302:15:302:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:305:21:305:52 | type assertion | test.go:302:15:302:36 | call to GetString : string | test.go:305:21:305:52 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:302:15:302:36 | call to GetString | user-provided value | test.go:0:0:0:0 | test.go | |

View File

@@ -23,7 +23,7 @@ nodes
| test.go:24:11:24:72 | type conversion | semmle.label | type conversion |
| test.go:24:18:24:71 | call to URLParam : string | semmle.label | call to URLParam : string |
#select
| test.go:21:11:21:24 | type conversion | test.go:13:12:13:16 | selection of URL : pointer type | test.go:21:11:21:24 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:13:12:13:16 | selection of URL | user-provided value |
| test.go:22:11:22:46 | type conversion | test.go:22:18:22:45 | call to URLParam : string | test.go:22:11:22:46 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:18:22:45 | call to URLParam | user-provided value |
| test.go:23:11:23:61 | type conversion | test.go:23:18:23:60 | call to URLParamFromCtx : string | test.go:23:11:23:61 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:23:18:23:60 | call to URLParamFromCtx | user-provided value |
| test.go:24:11:24:72 | type conversion | test.go:24:18:24:71 | call to URLParam : string | test.go:24:11:24:72 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:24:18:24:71 | call to URLParam | user-provided value |
| test.go:21:11:21:24 | type conversion | test.go:13:12:13:16 | selection of URL : pointer type | test.go:21:11:21:24 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:13:12:13:16 | selection of URL | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:22:11:22:46 | type conversion | test.go:22:18:22:45 | call to URLParam : string | test.go:22:11:22:46 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:18:22:45 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:23:11:23:61 | type conversion | test.go:23:18:23:60 | call to URLParamFromCtx : string | test.go:23:11:23:61 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:23:18:23:60 | call to URLParamFromCtx | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:24:11:24:72 | type conversion | test.go:24:18:24:71 | call to URLParam : string | test.go:24:11:24:72 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:24:18:24:71 | call to URLParam | user-provided value | test.go:0:0:0:0 | test.go | |

View File

@@ -74,22 +74,22 @@ nodes
| test.go:162:11:162:32 | call to Param : string | semmle.label | call to Param : string |
| test.go:163:23:163:35 | type conversion | semmle.label | type conversion |
#select
| test.go:14:16:14:20 | param | test.go:13:11:13:32 | call to Param : string | test.go:14:16:14:20 | param | Cross-site scripting vulnerability due to $@. | test.go:13:11:13:32 | call to Param | user-provided value |
| test.go:20:16:20:20 | param | test.go:19:11:19:27 | call to ParamValues : slice type | test.go:20:16:20:20 | param | Cross-site scripting vulnerability due to $@. | test.go:19:11:19:27 | call to ParamValues | user-provided value |
| test.go:26:16:26:20 | param | test.go:25:11:25:37 | call to QueryParam : string | test.go:26:16:26:20 | param | Cross-site scripting vulnerability due to $@. | test.go:25:11:25:37 | call to QueryParam | user-provided value |
| test.go:32:16:32:20 | param | test.go:31:11:31:27 | call to QueryParams : Values | test.go:32:16:32:20 | param | Cross-site scripting vulnerability due to $@. | test.go:31:11:31:27 | call to QueryParams | user-provided value |
| test.go:38:16:38:19 | qstr | test.go:37:10:37:26 | call to QueryString : string | test.go:38:16:38:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:37:10:37:26 | call to QueryString | user-provided value |
| test.go:44:16:44:18 | val | test.go:43:9:43:34 | call to FormValue : string | test.go:44:16:44:18 | val | Cross-site scripting vulnerability due to $@. | test.go:43:9:43:34 | call to FormValue | user-provided value |
| test.go:50:16:50:37 | index expression | test.go:49:2:49:30 | ... := ...[0] : Values | test.go:50:16:50:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:49:2:49:30 | ... := ...[0] | user-provided value |
| test.go:59:20:59:25 | buffer | test.go:55:2:55:46 | ... := ...[0] : pointer type | test.go:59:20:59:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:55:2:55:46 | ... := ...[0] | user-provided value |
| test.go:65:16:65:41 | index expression | test.go:64:2:64:31 | ... := ...[0] : pointer type | test.go:65:16:65:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:64:2:64:31 | ... := ...[0] | user-provided value |
| test.go:75:20:75:25 | buffer | test.go:70:2:70:31 | ... := ...[0] : pointer type | test.go:75:20:75:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:70:2:70:31 | ... := ...[0] | user-provided value |
| test.go:81:16:81:24 | selection of Value | test.go:80:2:80:32 | ... := ...[0] : pointer type | test.go:81:16:81:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:80:2:80:32 | ... := ...[0] | user-provided value |
| test.go:87:16:87:31 | selection of Value | test.go:86:13:86:25 | call to Cookies : slice type | test.go:87:16:87:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:86:13:86:25 | call to Cookies | user-provided value |
| test.go:98:16:98:21 | selection of s | test.go:97:11:97:15 | &... : pointer type | test.go:98:16:98:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:97:11:97:15 | &... | user-provided value |
| test.go:112:16:112:42 | type assertion | test.go:111:21:111:42 | call to Param : string | test.go:112:16:112:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:111:21:111:42 | call to Param | user-provided value |
| test.go:123:16:123:20 | param | test.go:122:11:122:32 | call to Param : string | test.go:123:16:123:20 | param | Cross-site scripting vulnerability due to $@. | test.go:122:11:122:32 | call to Param | user-provided value |
| test.go:129:20:129:32 | type conversion | test.go:128:11:128:32 | call to Param : string | test.go:129:20:129:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:128:11:128:32 | call to Param | user-provided value |
| test.go:135:29:135:41 | type conversion | test.go:134:11:134:32 | call to Param : string | test.go:135:29:135:41 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:134:11:134:32 | call to Param | user-provided value |
| test.go:148:31:148:36 | reader | test.go:146:11:146:32 | call to Param : string | test.go:148:31:148:36 | reader | Cross-site scripting vulnerability due to $@. | test.go:146:11:146:32 | call to Param | user-provided value |
| test.go:163:23:163:35 | type conversion | test.go:162:11:162:32 | call to Param : string | test.go:163:23:163:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:162:11:162:32 | call to Param | user-provided value |
| test.go:14:16:14:20 | param | test.go:13:11:13:32 | call to Param : string | test.go:14:16:14:20 | param | Cross-site scripting vulnerability due to $@. | test.go:13:11:13:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:20:16:20:20 | param | test.go:19:11:19:27 | call to ParamValues : slice type | test.go:20:16:20:20 | param | Cross-site scripting vulnerability due to $@. | test.go:19:11:19:27 | call to ParamValues | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:26:16:26:20 | param | test.go:25:11:25:37 | call to QueryParam : string | test.go:26:16:26:20 | param | Cross-site scripting vulnerability due to $@. | test.go:25:11:25:37 | call to QueryParam | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:32:16:32:20 | param | test.go:31:11:31:27 | call to QueryParams : Values | test.go:32:16:32:20 | param | Cross-site scripting vulnerability due to $@. | test.go:31:11:31:27 | call to QueryParams | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:38:16:38:19 | qstr | test.go:37:10:37:26 | call to QueryString : string | test.go:38:16:38:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:37:10:37:26 | call to QueryString | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:44:16:44:18 | val | test.go:43:9:43:34 | call to FormValue : string | test.go:44:16:44:18 | val | Cross-site scripting vulnerability due to $@. | test.go:43:9:43:34 | call to FormValue | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:50:16:50:37 | index expression | test.go:49:2:49:30 | ... := ...[0] : Values | test.go:50:16:50:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:49:2:49:30 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:59:20:59:25 | buffer | test.go:55:2:55:46 | ... := ...[0] : pointer type | test.go:59:20:59:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:55:2:55:46 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:65:16:65:41 | index expression | test.go:64:2:64:31 | ... := ...[0] : pointer type | test.go:65:16:65:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:64:2:64:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:75:20:75:25 | buffer | test.go:70:2:70:31 | ... := ...[0] : pointer type | test.go:75:20:75:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:70:2:70:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:81:16:81:24 | selection of Value | test.go:80:2:80:32 | ... := ...[0] : pointer type | test.go:81:16:81:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:80:2:80:32 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:87:16:87:31 | selection of Value | test.go:86:13:86:25 | call to Cookies : slice type | test.go:87:16:87:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:86:13:86:25 | call to Cookies | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:98:16:98:21 | selection of s | test.go:97:11:97:15 | &... : pointer type | test.go:98:16:98:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:97:11:97:15 | &... | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:112:16:112:42 | type assertion | test.go:111:21:111:42 | call to Param : string | test.go:112:16:112:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:111:21:111:42 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:123:16:123:20 | param | test.go:122:11:122:32 | call to Param : string | test.go:123:16:123:20 | param | Cross-site scripting vulnerability due to $@. | test.go:122:11:122:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:129:20:129:32 | type conversion | test.go:128:11:128:32 | call to Param : string | test.go:129:20:129:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:128:11:128:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:135:29:135:41 | type conversion | test.go:134:11:134:32 | call to Param : string | test.go:135:29:135:41 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:134:11:134:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:148:31:148:36 | reader | test.go:146:11:146:32 | call to Param : string | test.go:148:31:148:36 | reader | Cross-site scripting vulnerability due to $@. | test.go:146:11:146:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:163:23:163:35 | type conversion | test.go:162:11:162:32 | call to Param : string | test.go:163:23:163:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:162:11:162:32 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |

View File

@@ -27,69 +27,69 @@ type MyRoute struct {
func (c MyRoute) Handler1() revel.Result {
// GOOD: the Render function is likely to properly escape the user-controlled parameter.
return c.Render("someviewparam", c.Params.Form.Get("someField"))
return c.Render("someviewparam", c.Params.Form.Get("someField")) // $source=selection of Params
}
func (c MyRoute) Handler2() revel.Result {
// BAD: the RenderBinary function copies an `io.Reader` to the user's browser.
buf := &bytes.Buffer{}
buf.WriteString(c.Params.Form.Get("someField"))
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now())
buf.WriteString(c.Params.Form.Get("someField")) // $source=selection of Params
return c.RenderBinary(buf, "index.html", revel.Inline, time.Now()) // $responsebody=buf
}
func (c MyRoute) Handler3() revel.Result {
// GOOD: the RenderBinary function copies an `io.Reader` to the user's browser, but the filename
// means it will be given a safe content-type.
buf := &bytes.Buffer{}
buf.WriteString(c.Params.Form.Get("someField"))
return c.RenderBinary(buf, "index.txt", revel.Inline, time.Now())
buf.WriteString(c.Params.Form.Get("someField")) // $source=selection of Params
return c.RenderBinary(buf, "index.txt", revel.Inline, time.Now()) // $responsebody=buf
}
func (c MyRoute) Handler4() revel.Result {
// GOOD: the RenderError function either uses an HTML template with probable escaping,
// or it uses content-type text/plain.
err := errors.New(c.Params.Form.Get("someField"))
return c.RenderError(err)
err := errors.New(c.Params.Form.Get("someField")) // $source=selection of Params
return c.RenderError(err) // $responsebody=err
}
func (c MyRoute) Handler5() revel.Result {
// BAD: returning an arbitrary file (but this is detected at the os.Open call, not
// due to modelling Revel)
f, _ := os.Open(c.Params.Form.Get("someField"))
f, _ := os.Open(c.Params.Form.Get("someField")) // $source=selection of Params
return c.RenderFile(f, revel.Inline)
}
func (c MyRoute) Handler6() revel.Result {
// BAD: returning an arbitrary file (detected as a user-controlled file-op, not XSS)
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline)
return c.RenderFileName(c.Params.Form.Get("someField"), revel.Inline) // $source=selection of Params
}
func (c MyRoute) Handler7() revel.Result {
// BAD: straightforward XSS
return c.RenderHTML(c.Params.Form.Get("someField"))
return c.RenderHTML(c.Params.Form.Get("someField")) // $responsebody=call to Get $source=selection of Params
}
func (c MyRoute) Handler8() revel.Result {
// GOOD: uses JSON content-type
return c.RenderJSON(c.Params.Form.Get("someField"))
return c.RenderJSON(c.Params.Form.Get("someField")) // $responsebody=call to Get $source=selection of Params
}
func (c MyRoute) Handler9() revel.Result {
// GOOD: uses Javascript content-type
return c.RenderJSONP("callback", c.Params.Form.Get("someField"))
return c.RenderJSONP("callback", c.Params.Form.Get("someField")) // $responsebody=call to Get $source=selection of Params
}
func (c MyRoute) Handler10() revel.Result {
// GOOD: uses text content-type
return c.RenderText(c.Params.Form.Get("someField"))
return c.RenderText(c.Params.Form.Get("someField")) // $responsebody=call to Get $source=selection of Params
}
func (c MyRoute) Handler11() revel.Result {
// GOOD: uses xml content-type
return c.RenderXML(c.Params.Form.Get("someField"))
return c.RenderXML(c.Params.Form.Get("someField")) // $responsebody=call to Get $source=selection of Params
}
func (c MyRoute) Handler12() revel.Result {
// BAD: open redirect
return c.Redirect(c.Params.Form.Get("someField"))
return c.Redirect(c.Params.Form.Get("someField")) // $source=selection of Params
}

View File

@@ -11,6 +11,24 @@ edges
| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:29 | implicit dereference : Params |
| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:29 | selection of Params : pointer type |
| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get |
| Revel.go:70:22:70:29 | implicit dereference : Params | Revel.go:70:22:70:29 | implicit dereference : Params |
| Revel.go:70:22:70:29 | implicit dereference : Params | Revel.go:70:22:70:29 | selection of Params : pointer type |
| Revel.go:70:22:70:29 | implicit dereference : Params | Revel.go:70:22:70:35 | selection of Query |
| Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:29 | implicit dereference : Params |
| Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:29 | selection of Params : pointer type |
| Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query |
| examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL | examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL |
| examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL | examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type |
| examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL | examples/booking/app/init.go:36:44:36:53 | selection of Path |
| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL |
| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type |
| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:53 | selection of Path |
| examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL | examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL |
| examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL | examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type |
| examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL | examples/booking/app/init.go:40:49:40:58 | selection of Path |
| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL |
| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type |
| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:58 | selection of Path |
nodes
| EndToEnd.go:36:18:36:25 | implicit dereference : Params | semmle.label | implicit dereference : Params |
| EndToEnd.go:36:18:36:25 | selection of Params : pointer type | semmle.label | selection of Params : pointer type |
@@ -18,6 +36,18 @@ nodes
| EndToEnd.go:69:22:69:29 | implicit dereference : Params | semmle.label | implicit dereference : Params |
| EndToEnd.go:69:22:69:29 | selection of Params : pointer type | semmle.label | selection of Params : pointer type |
| EndToEnd.go:69:22:69:51 | call to Get | semmle.label | call to Get |
| Revel.go:70:22:70:29 | implicit dereference : Params | semmle.label | implicit dereference : Params |
| Revel.go:70:22:70:29 | selection of Params : pointer type | semmle.label | selection of Params : pointer type |
| Revel.go:70:22:70:35 | selection of Query | semmle.label | selection of Query |
| examples/booking/app/init.go:36:44:36:48 | implicit dereference : URL | semmle.label | implicit dereference : URL |
| examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | semmle.label | selection of URL : pointer type |
| examples/booking/app/init.go:36:44:36:53 | selection of Path | semmle.label | selection of Path |
| examples/booking/app/init.go:40:49:40:53 | implicit dereference : URL | semmle.label | implicit dereference : URL |
| examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | semmle.label | selection of URL : pointer type |
| examples/booking/app/init.go:40:49:40:58 | selection of Path | semmle.label | selection of Path |
#select
| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params : pointer type | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value |
| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value |
| EndToEnd.go:37:24:37:26 | buf | EndToEnd.go:36:18:36:25 | selection of Params : pointer type | EndToEnd.go:37:24:37:26 | buf | Cross-site scripting vulnerability due to $@. | EndToEnd.go:36:18:36:25 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| EndToEnd.go:69:22:69:51 | call to Get | EndToEnd.go:69:22:69:29 | selection of Params : pointer type | EndToEnd.go:69:22:69:51 | call to Get | Cross-site scripting vulnerability due to $@. | EndToEnd.go:69:22:69:29 | selection of Params | user-provided value | EndToEnd.go:0:0:0:0 | EndToEnd.go | |
| Revel.go:70:22:70:35 | selection of Query | Revel.go:70:22:70:29 | selection of Params : pointer type | Revel.go:70:22:70:35 | selection of Query | Cross-site scripting vulnerability due to $@. This template argument is instantiated raw $@. | Revel.go:70:22:70:29 | selection of Params | user-provided value | views/myAppController/rawRead.html:1:1:2:9 | {{raw .Foo}}\n{{.Bar}}\n | here |
| examples/booking/app/init.go:36:44:36:53 | selection of Path | examples/booking/app/init.go:36:44:36:48 | selection of URL : pointer type | examples/booking/app/init.go:36:44:36:53 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:36:44:36:48 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |
| examples/booking/app/init.go:40:49:40:58 | selection of Path | examples/booking/app/init.go:40:49:40:53 | selection of URL : pointer type | examples/booking/app/init.go:40:49:40:58 | selection of Path | Cross-site scripting vulnerability due to $@. | examples/booking/app/init.go:40:49:40:53 | selection of URL | user-provided value | examples/booking/app/init.go:0:0:0:0 | examples/booking/app/init.go | |

View File

@@ -4,8 +4,6 @@ package main
import (
"io/ioutil"
"mime/multipart"
"net/url"
"github.com/revel/revel"
)
@@ -22,115 +20,111 @@ type person struct {
Address string `form:"address"`
}
func useString(val string) {}
func useFiles(val *multipart.FileHeader) {}
func useJSON(val []byte) {}
func useURLValues(v url.Values) {
useString(v["key"][0])
useString(v.Get("key"))
}
func usePerson(p person) {}
func sink(_ ...interface{}) {}
func (c myAppController) accessingParamsDirectlyIsUnsafe() {
useString(c.Params.Get("key")) // NOT OK
useURLValues(c.Params.Values) // NOT OK
sink(c.Params.Get("key"))
sink(c.Params.Values) // $source=selection of Params
val4 := ""
c.Params.Bind(&val4, "key") // NOT OK
useString(val4)
c.Params.Bind(&val4, "key") // $source=selection of Params
sink(val4)
useString(c.Request.FormValue("key")) // NOT OK
sink(c.Request.FormValue("key"))
}
func (c myAppController) accessingFixedIsSafe(mainRouter *revel.Router) {
useURLValues(c.Params.Fixed) // OK
useString(mainRouter.Route(c.Request).FixedParams[0]) // OK
sink(c.Params.Fixed.Get("key")) // $noflow
sink(mainRouter.Route(c.Request).FixedParams[0]) // $noflow
}
func (c myAppController) accessingRouteIsUnsafe(mainRouter *revel.Router) {
useURLValues(c.Params.Route) // NOT OK
useURLValues(mainRouter.Route(c.Request).Params) // NOT OK
sink(c.Params.Route["key"][0])
sink(mainRouter.Route(c.Request).Params["key"][0])
}
func (c myAppController) accessingParamsQueryIsUnsafe() {
useURLValues(c.Params.Query) // NOT OK
sink(c.Params.Query["key"][0])
}
func (c myAppController) accessingParamsFormIsUnsafe() {
useURLValues(c.Params.Form) // NOT OK
useString(c.Request.PostFormValue("key")) // NOT OK
sink(c.Params.Form["key"][0])
sink(c.Request.PostFormValue("key"))
}
func (c myAppController) accessingParamsFilesIsUnsafe() {
useFiles(c.Params.Files["key"][0]) // NOT OK
sink(c.Params.Files["key"][0])
}
func (c myAppController) accessingParamsJSONIsUnsafe() {
useJSON(c.Params.JSON) // NOT OK
sink(c.Params.JSON)
var val2 map[string]interface{}
c.Params.BindJSON(&val2) // NOT OK
useString(val2["name"].(string))
c.Params.BindJSON(&val2)
sink(val2["name"].(string))
}
func (c myAppController) rawRead() { // $responsebody=argument corresponding to c
c.ViewArgs["Foo"] = "<p>raw HTML</p>" // $responsebody="<p>raw HTML</p>"
c.ViewArgs["Bar"] = "<p>not raw HTML</p>"
c.ViewArgs["Foo"] = c.Params.Query // $responsebody=selection of Query
c.Render()
}
func accessingRequestDirectlyIsUnsafe(c *revel.Controller) {
useURLValues(c.Request.GetQuery()) // NOT OK
useURLValues(c.Request.Form) // NOT OK
useURLValues(c.Request.MultipartForm.Value) // NOT OK
useString(c.Request.ContentType) // NOT OK
useString(c.Request.AcceptLanguages[0].Language) // NOT OK
useString(c.Request.Locale) // NOT OK
sink(c.Request.GetQuery()["key"][0])
sink(c.Request.Form["key"][0])
sink(c.Request.MultipartForm.Value["key"][0])
sink(c.Request.ContentType)
sink(c.Request.AcceptLanguages[0].Language)
sink(c.Request.Locale)
form, _ := c.Request.GetForm() // NOT OK
useURLValues(form)
form, _ := c.Request.GetForm()
sink(form["key"][0])
smp1, _ := c.Request.GetMultipartForm() // NOT OK
useURLValues(smp1.GetValues())
smp1, _ := c.Request.GetMultipartForm()
sink(smp1.GetValues()["key"][0])
smp2, _ := c.Request.GetMultipartForm() // NOT OK
useFiles(smp2.GetFiles()["key"][0])
smp2, _ := c.Request.GetMultipartForm()
sink(smp2.GetFiles()["key"][0])
useFiles(c.Request.MultipartForm.File["key"][0]) // NOT OK
sink(c.Request.MultipartForm.File["key"][0])
json, _ := ioutil.ReadAll(c.Request.GetBody()) // NOT OK
useJSON(json)
json, _ := ioutil.ReadAll(c.Request.GetBody())
sink(json)
cookie, _ := c.Request.Cookie("abc")
useString(cookie.GetValue()) // NOT OK
sink(cookie.GetValue())
useString(c.Request.GetHttpHeader("headername")) // NOT OK
sink(c.Request.GetHttpHeader("headername"))
useString(c.Request.GetRequestURI()) // NOT OK
sink(c.Request.GetRequestURI())
reader, _ := c.Request.MultipartReader()
part, _ := reader.NextPart()
partbody := make([]byte, 100)
part.Read(partbody)
useString(string(partbody)) // NOT OK
sink(string(partbody))
useString(c.Request.Referer()) // NOT OK
sink(c.Request.Referer())
useString(c.Request.UserAgent()) // NOT OK
sink(c.Request.UserAgent())
}
func accessingServerRequest(c *revel.Controller) {
var message string
c.Request.WebSocket.MessageReceive(&message) // NOT OK
useString(message)
c.Request.WebSocket.MessageReceive(&message)
sink(message)
var p person
c.Request.WebSocket.MessageReceiveJSON(&p) // NOT OK
usePerson(p)
c.Request.WebSocket.MessageReceiveJSON(&p)
sink(p)
}
func accessingHeaders(c *revel.Controller) {
tainted := c.Request.Header.Get("somekey") // NOT OK
useString(tainted)
tainted := c.Request.Header.Get("somekey")
sink(tainted)
tainted2 := c.Request.Header.GetAll("somekey") // NOT OK
useString(tainted2[0])
tainted2 := c.Request.Header.GetAll("somekey")
sink(tainted2[0])
}

View File

@@ -1,43 +0,0 @@
| Revel.go:39:12:39:19 | selection of Params : pointer type | Revel.go:39:12:39:30 | call to Get | 39 |
| Revel.go:40:15:40:22 | selection of Params : pointer type | Revel.go:32:12:32:22 | index expression | 40 |
| Revel.go:40:15:40:22 | selection of Params : pointer type | Revel.go:33:12:33:23 | call to Get | 40 |
| Revel.go:43:2:43:9 | selection of Params : pointer type | Revel.go:44:12:44:15 | val4 | 43 |
| Revel.go:46:12:46:37 | call to FormValue | Revel.go:46:12:46:37 | call to FormValue | 46 |
| Revel.go:55:15:55:22 | selection of Params : pointer type | Revel.go:32:12:32:22 | index expression | 55 |
| Revel.go:55:15:55:22 | selection of Params : pointer type | Revel.go:33:12:33:23 | call to Get | 55 |
| Revel.go:56:15:56:48 | selection of Params : map type | Revel.go:32:12:32:22 | index expression | 56 |
| Revel.go:56:15:56:48 | selection of Params : map type | Revel.go:33:12:33:23 | call to Get | 56 |
| Revel.go:60:15:60:22 | selection of Params : pointer type | Revel.go:32:12:32:22 | index expression | 60 |
| Revel.go:60:15:60:22 | selection of Params : pointer type | Revel.go:33:12:33:23 | call to Get | 60 |
| Revel.go:64:15:64:22 | selection of Params : pointer type | Revel.go:32:12:32:22 | index expression | 64 |
| Revel.go:64:15:64:22 | selection of Params : pointer type | Revel.go:33:12:33:23 | call to Get | 64 |
| Revel.go:65:12:65:41 | call to PostFormValue | Revel.go:65:12:65:41 | call to PostFormValue | 65 |
| Revel.go:69:11:69:18 | selection of Params : pointer type | Revel.go:69:11:69:34 | index expression | 69 |
| Revel.go:73:10:73:17 | selection of Params : pointer type | Revel.go:73:10:73:22 | selection of JSON | 73 |
| Revel.go:76:2:76:9 | selection of Params : pointer type | Revel.go:77:12:77:32 | type assertion | 76 |
| Revel.go:81:15:81:34 | call to GetQuery : Values | Revel.go:32:12:32:22 | index expression | 81 |
| Revel.go:81:15:81:34 | call to GetQuery : Values | Revel.go:33:12:33:23 | call to Get | 81 |
| Revel.go:82:15:82:28 | selection of Form : Values | Revel.go:32:12:32:22 | index expression | 82 |
| Revel.go:82:15:82:28 | selection of Form : Values | Revel.go:33:12:33:23 | call to Get | 82 |
| Revel.go:83:15:83:37 | selection of MultipartForm : pointer type | Revel.go:32:12:32:22 | index expression | 83 |
| Revel.go:83:15:83:37 | selection of MultipartForm : pointer type | Revel.go:33:12:33:23 | call to Get | 83 |
| Revel.go:84:12:84:32 | selection of ContentType | Revel.go:84:12:84:32 | selection of ContentType | 84 |
| Revel.go:85:12:85:36 | selection of AcceptLanguages : AcceptLanguages | Revel.go:85:12:85:48 | selection of Language | 85 |
| Revel.go:86:12:86:27 | selection of Locale | Revel.go:86:12:86:27 | selection of Locale | 86 |
| Revel.go:88:13:88:31 | call to GetForm : tuple type | Revel.go:32:12:32:22 | index expression | 88 |
| Revel.go:88:13:88:31 | call to GetForm : tuple type | Revel.go:33:12:33:23 | call to Get | 88 |
| Revel.go:91:13:91:40 | call to GetMultipartForm : tuple type | Revel.go:32:12:32:22 | index expression | 91 |
| Revel.go:91:13:91:40 | call to GetMultipartForm : tuple type | Revel.go:33:12:33:23 | call to Get | 91 |
| Revel.go:94:13:94:40 | call to GetMultipartForm : tuple type | Revel.go:95:11:95:35 | index expression | 94 |
| Revel.go:97:11:97:33 | selection of MultipartForm : pointer type | Revel.go:97:11:97:48 | index expression | 97 |
| Revel.go:99:28:99:46 | call to GetBody : Reader | Revel.go:100:10:100:13 | json | 99 |
| Revel.go:102:15:102:37 | call to Cookie : tuple type | Revel.go:103:12:103:28 | call to GetValue | 102 |
| Revel.go:105:12:105:48 | call to GetHttpHeader | Revel.go:105:12:105:48 | call to GetHttpHeader | 105 |
| Revel.go:107:12:107:36 | call to GetRequestURI | Revel.go:107:12:107:36 | call to GetRequestURI | 107 |
| Revel.go:109:15:109:41 | call to MultipartReader : tuple type | Revel.go:113:12:113:27 | type conversion | 109 |
| Revel.go:115:12:115:30 | call to Referer | Revel.go:115:12:115:30 | call to Referer | 115 |
| Revel.go:117:12:117:32 | call to UserAgent | Revel.go:117:12:117:32 | call to UserAgent | 117 |
| Revel.go:122:37:122:44 | &... : pointer type | Revel.go:123:12:123:18 | message | 122 |
| Revel.go:126:41:126:42 | &... : pointer type | Revel.go:127:12:127:12 | p | 126 |
| Revel.go:131:13:131:28 | selection of Header : pointer type | Revel.go:132:12:132:18 | tainted | 131 |
| Revel.go:134:14:134:29 | selection of Header : pointer type | Revel.go:135:12:135:22 | index expression | 134 |

View File

@@ -1,19 +0,0 @@
import go
class SinkFunction extends Function {
SinkFunction() { this.getName() = ["useFiles", "useJSON", "usePerson", "useString"] }
}
class TestConfig extends TaintTracking::Configuration {
TestConfig() { this = "testconfig" }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink = any(SinkFunction f).getACall().getAnArgument()
}
}
from TaintTracking::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, int i
where config.hasFlowPath(source, sink) and source.hasLocationInfo(_, i, _, _, _)
select source, sink, i order by i

View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (C) 2012-2018 The Revel Framework Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,3 @@
Revel example adapted from [revel-examples](https://github.com/revel/revel-examples).
See `LICENSE` for license information.

View File

@@ -0,0 +1,98 @@
package controllers
import (
"github.com/revel/revel"
"codeql-go-tests/frameworks/Revel/examples/booking/app/models"
"github.com/revel/modules/orm/gorp/app/controllers"
)
type Application struct {
gorpController.Controller
}
func (c Application) AddUser() revel.Result {
if user := c.connected(); user != nil {
c.ViewArgs["user"] = user
}
return nil
}
func (c Application) connected() *models.User {
if c.ViewArgs["user"] != nil {
return c.ViewArgs["user"].(*models.User)
}
if username, ok := c.Session["user"]; ok {
return c.getUser(username.(string))
}
return nil
}
func (c Application) getUser(username string) (user *models.User) {
user = &models.User{}
c.Session.GetInto("fulluser", user, false)
if user.Username == username {
return user
}
c.Session["fulluser"] = user
return
}
func (c Application) Index() revel.Result {
if c.connected() != nil {
return c.Redirect(nil)
}
c.Flash.Error("Please log in first")
return c.Render()
}
func (c Application) Register() revel.Result {
return c.Render()
}
func (c Application) SaveUser(user models.User, verifyPassword string) revel.Result {
c.Validation.Required(verifyPassword)
c.Validation.Required(verifyPassword == user.Password).
MessageKey("Password does not match")
user.Validate(c.Validation)
if c.Validation.HasErrors() {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(nil)
}
c.Session["user"] = user.Username
c.Flash.Success("Welcome, " + user.Name)
return c.Redirect(nil)
}
func (c Application) Login(username, password string, remember bool) revel.Result {
user := c.getUser(username)
if user != nil {
var err error
if err == nil {
c.Session["user"] = username
if remember {
c.Session.SetDefaultExpiration()
} else {
c.Session.SetNoExpiration()
}
c.Flash.Success("Welcome, " + username)
return c.Redirect(nil)
}
}
c.Flash.Out["username"] = username
c.Flash.Error("Login failed")
return c.Redirect(nil)
}
func (c Application) Logout() revel.Result {
for k := range c.Session {
delete(c.Session, k)
}
return c.Redirect(nil)
}

View File

@@ -0,0 +1,196 @@
//go:generate swagger generate spec -o swagger.json
// Package classification Swagger Hotel Example.
// Swagger Hotel Example
//
//
//
// Schemes: https
// Host: hotel.example.revelframework.com
// BasePath: /
// Version: 1.0.0
// License: MIT http://opensource.org/licenses/MIT
// Contact: Name<email@somehwere.com> https://www.somewhere.com
//
// Consumes:
// - application/json
// - application/x-www-form-urlencoded
//
// Produces:
// - text/html
//
//
//
//
// swagger:meta
package controllers
import (
"fmt"
"strings"
"codeql-go-tests/frameworks/Revel/examples/booking/app/models"
"github.com/revel/revel"
)
type Hotels struct {
Application
}
func (c Hotels) checkUser() revel.Result {
if user := c.connected(); user == nil {
c.Flash.Error("Please log in first")
return c.Redirect(nil)
}
return nil
}
func (c Hotels) Index() revel.Result {
c.Log.Info("Fetching index")
var bookings []*models.Booking
return c.Render(bookings)
}
// swagger:route GET /hotels/ListJson enter demo
//
// Enter Demo
//
//
// Consumes:
// - application/x-www-form-urlencoded
//
// Produces:
// - text/html
//
// Schemes: https
//
//
// Responses:
// 200: Success
// 401: Invalid User
// swagger:operation GET /demo demo
//
// Enter Demo
//
//
// ---
// produces:
// - text/html
// parameters:
// - name: user
// in: formData
// description: user
// required: true
// type: string
// - name: demo
// in: formData
// description: demo
// required: true
// type: string
// responses:
// '200':
// description: Success
// '401':
// description: Invalid User
func (c Hotels) ListJson(search string, size, page uint64) revel.Result {
if page == 0 {
page = 1
}
nextPage := page + 1
search = strings.TrimSpace(search)
var hotels []*models.Hotel
return c.RenderJSON(map[string]interface{}{"hotels": hotels, "search": search, "size": size, "page": page, "nextPage": nextPage}) // $responsebody=map literal
}
func (c Hotels) List(search string, size, page uint64) revel.Result {
if page == 0 {
page = 1
}
nextPage := page + 1
search = strings.TrimSpace(search)
var hotels []*models.Hotel
return c.Render(hotels, search, size, page, nextPage)
}
func (c Hotels) loadHotelById(id int) *models.Hotel {
var h interface{}
if h == nil {
return nil
}
return h.(*models.Hotel)
}
func (c Hotels) Show(id int) revel.Result {
hotel := c.loadHotelById(id)
if hotel == nil {
return c.NotFound("Hotel %d does not exist", id)
}
title := hotel.Name
return c.Render(title, hotel)
}
func (c Hotels) Settings() revel.Result {
return c.Render()
}
func (c Hotels) SaveSettings(password, verifyPassword string) revel.Result {
models.ValidatePassword(c.Validation, password)
c.Validation.Required(verifyPassword).
Message("Please verify your password")
c.Validation.Required(verifyPassword == password).
Message("Your password doesn't match")
if c.Validation.HasErrors() {
c.Validation.Keep()
return c.Redirect(nil)
}
c.Flash.Success("Password updated")
return c.Redirect(nil)
}
func (c Hotels) ConfirmBooking(id int, booking models.Booking) revel.Result {
hotel := c.loadHotelById(id) // $responsebody=call to loadHotelById
if hotel == nil {
return c.NotFound("Hotel %d does not exist", id)
}
title := fmt.Sprintf("Confirm %s booking", hotel.Name)
booking.Hotel = hotel
booking.User = c.connected()
booking.Validate(c.Validation)
if c.Validation.HasErrors() || c.Params.Get("revise") != "" {
c.Validation.Keep()
c.FlashParams()
return c.Redirect(nil)
}
if c.Params.Get("confirm") != "" {
c.Flash.Success("Thank you, %s, your confirmation number for %s is %d",
booking.User.Name, hotel.Name, booking.BookingId)
return c.Redirect(nil)
}
return c.Render(title, hotel, booking)
}
func (c Hotels) CancelBooking(id int) revel.Result {
c.Flash.Success(fmt.Sprintln("Booking cancelled for confirmation number", id))
return c.Redirect(nil)
}
func (c Hotels) Book(id int) revel.Result {
hotel := c.loadHotelById(id)
if hotel == nil {
return c.NotFound("Hotel %d does not exist", id)
}
title := "Book " + hotel.Name
return c.Render(title, hotel)
}

View File

@@ -0,0 +1,8 @@
package controllers
import "github.com/revel/revel"
func init() {
revel.InterceptMethod(Application.AddUser, revel.BEFORE)
revel.InterceptMethod(Hotels.checkUser, revel.BEFORE)
}

View File

@@ -0,0 +1,57 @@
package app
import (
"fmt"
"github.com/revel/revel"
"github.com/revel/revel/logger"
"net/http"
"os"
)
func init() {
// Filters is the default set of global filters.
revel.Filters = []revel.Filter{
revel.PanicFilter, // Recover from panics and display an error page instead.
revel.RouterFilter, // Use the routing table to select the right Action
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
revel.ParamsFilter, // Parse parameters into Controller.Params.
revel.SessionFilter, // Restore and write the session cookie.
revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
revel.I18nFilter, // Resolve the requested language
HeaderFilter, // Add some security based headers
revel.InterceptorFilter, // Run interceptors around the action.
revel.CompressFilter, // Compress the result.
revel.ActionInvoker, // Invoke the action.
}
logger.LogFunctionMap["stdoutjson"] =
func(c *logger.CompositeMultiHandler, options *logger.LogOptions) {
// Set the json formatter to os.Stdout, replace any existing handlers for the level specified
c.SetJson(os.Stdout, options)
}
revel.AddInitEventHandler(func(event revel.Event, i interface{}) revel.EventResponse {
switch event {
case revel.ENGINE_BEFORE_INITIALIZED:
revel.AddHTTPMux("/this/is/a/test", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hi there, it worked", r.URL.Path) // $responsebody=selection of Path $responsebody="Hi there, it worked"
w.WriteHeader(200)
}))
revel.AddHTTPMux("/this/is/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hi there, shorter prefix", r.URL.Path) // $responsebody=selection of Path $responsebody="Hi there, shorter prefix"
w.WriteHeader(200)
}))
}
return 0
})
revel.OnAppStart(func() {}, 5)
}
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
// Add some common security headers
c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")
fc[0](c, fc[1:]) // Execute the next filter stage.
}

View File

@@ -0,0 +1,100 @@
package models
import (
"fmt"
"github.com/revel/revel"
"regexp"
"time"
)
type Booking struct {
BookingId int
UserId int
HotelId int
CheckInStr string
CheckOutStr string
CardNumber string
NameOnCard string
CardExpMonth int
CardExpYear int
Smoking bool
Beds int
// Transient
CheckInDate time.Time
CheckOutDate time.Time
User *User
Hotel *Hotel
}
// TODO: Make an interface for Validate() and then validation can pass in the
// key prefix ("booking.")
func (booking Booking) Validate(v *revel.Validation) {
v.Required(booking.User)
v.Required(booking.Hotel)
v.Required(booking.CheckInDate)
v.Required(booking.CheckOutDate)
v.Match(booking.CardNumber, regexp.MustCompile(`\d{16}`)).
Message("Credit card number must be numeric and 16 digits")
v.Check(booking.NameOnCard,
revel.Required{},
revel.MinSize{3},
revel.MaxSize{70},
)
}
func (b Booking) Total() int {
return b.Hotel.Price * b.Nights()
}
func (b Booking) Nights() int {
return int((b.CheckOutDate.Unix() - b.CheckInDate.Unix()) / 60 / 60 / 24)
}
const (
DATE_FORMAT = "Jan _2, 2006"
SQL_DATE_FORMAT = "2006-01-02"
)
func (b Booking) Description() string {
if b.Hotel == nil {
return ""
}
return fmt.Sprintf("%s, %s to %s",
b.Hotel.Name,
b.CheckInDate.Format(DATE_FORMAT),
b.CheckOutDate.Format(DATE_FORMAT))
}
func (b Booking) String() string {
return fmt.Sprintf("Booking(%s,%s)", b.User, b.Hotel.Name)
}
// These hooks work around two things:
// - Gorp's lack of support for loading relations automatically.
// - Sqlite's lack of support for datetimes.
func (b *Booking) PreInsert(_ interface{}) error {
b.UserId = b.User.UserId
b.HotelId = b.Hotel.HotelId
b.CheckInStr = b.CheckInDate.Format(SQL_DATE_FORMAT)
b.CheckOutStr = b.CheckOutDate.Format(SQL_DATE_FORMAT)
return nil
}
func (b *Booking) PostGet(exe interface{}) error {
var (
err error
)
if b.CheckInDate, err = time.Parse(SQL_DATE_FORMAT, b.CheckInStr); err != nil {
return fmt.Errorf("Error parsing check in date '%s' %s:", b.CheckInStr, err.Error())
}
if b.CheckOutDate, err = time.Parse(SQL_DATE_FORMAT, b.CheckOutStr); err != nil {
return fmt.Errorf("Error parsing check out date '%s' %s:", b.CheckOutStr, err.Error())
}
return nil
}

View File

@@ -0,0 +1,45 @@
package models
import (
"github.com/revel/revel"
)
type Hotel struct {
HotelId int
Name, Address string
City, State, Zip string
Country string
Price int
}
func (hotel *Hotel) Validate(v *revel.Validation) {
v.Check(hotel.Name,
revel.Required{},
revel.MaxSize{50},
)
v.MaxSize(hotel.Address, 100)
v.Check(hotel.City,
revel.Required{},
revel.MaxSize{40},
)
v.Check(hotel.State,
revel.Required{},
revel.MaxSize{6},
revel.MinSize{2},
)
v.Check(hotel.Zip,
revel.Required{},
revel.MaxSize{6},
revel.MinSize{5},
)
v.Check(hotel.Country,
revel.Required{},
revel.MaxSize{40},
revel.MinSize{2},
)
}

View File

@@ -0,0 +1,45 @@
package models
import (
"fmt"
"github.com/revel/revel"
"regexp"
)
type User struct {
UserId int
Name string
Username, Password string
HashedPassword []byte
}
func (u *User) String() string {
return fmt.Sprintf("User(%s)", u.Username)
}
var userRegex = regexp.MustCompile("^\\w*$")
func (user *User) Validate(v *revel.Validation) {
v.Check(user.Username,
revel.Required{},
revel.MaxSize{15},
revel.MinSize{4},
revel.Match{userRegex},
)
ValidatePassword(v, user.Password).
Key("user.Password")
v.Check(user.Name,
revel.Required{},
revel.MaxSize{100},
)
}
func ValidatePassword(v *revel.Validation, password string) *revel.ValidationResult {
return v.Check(password,
revel.Required{},
revel.MaxSize{15},
revel.MinSize{5},
)
}

View File

@@ -0,0 +1,114 @@
{{append . "moreStyles" "ui-lightness/jquery-ui-1.7.2.custom.css"}}
{{append . "moreScripts" "js/jquery-ui-1.7.2.custom.min.js"}}
{{template "header.html" .}}
<h1>Book hotel</h1>
<form method="POST" action="{{url "Hotels.Book" .hotel.HotelId}}">
<p>
<strong>Name:</strong> {{.hotel.Name}}
</p>
<p>
<strong>Address:</strong> {{.hotel.Address}}
</p>
<p>
<strong>City:</strong> {{.hotel.City}}
</p>
<p>
<strong>State:</strong> {{.hotel.State}}
</p>
<p>
<strong>Zip:</strong> {{.hotel.Zip}}
</p>
<p>
<strong>Country:</strong> {{.hotel.Country}}
</p>
<p>
<strong>Nightly rate:</strong> {{.hotel.Price}}
</p>
{{with $field := field "booking.CheckInDate" .}}
<p class="{{$field.ErrorClass}}">
<strong>Check In Date:</strong>
<input type="text" size="10" name="{{$field.Name}}" class="datepicker" value="{{$field.Flash}}">
* <span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "booking.CheckOutDate" .}}
<p class="{{$field.ErrorClass}}">
<strong>Check Out Date:</strong>
<input type="text" size="10" name="{{$field.Name}}" class="datepicker" value="{{$field.Flash}}">
* <span class="error">{{$field.Error}}</span>
</p>
{{end}}
<p>
<strong>Room preference:</strong>
{{with $field := field "booking.Beds" .}}
<select name="{{$field.Name}}">
{{option $field "1" "One king-size bed"}}
{{option $field "2" "Two double beds"}}
{{option $field "3" "Three beds"}}
</select>
{{end}}
</p>
<p>
<strong>Smoking preference:</strong>
{{with $field := field "booking.Smoking" .}}
{{radio $field "true"}} Smoking
{{radio $field "false"}} Non smoking
{{end}}
</p>
{{with $field := field "booking.CardNumber" .}}
<p class="{{$field.ErrorClass}}">
<strong>Credit Card #:</strong>
<input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}">
* <span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "booking.NameOnCard" .}}
<p class="{{$field.ErrorClass}}">
<strong>Credit Card Name:</strong>
<input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}">
* <span class="error">{{$field.Error}}</span>
</p>
{{end}}
<p>
<strong>Credit Card Expiry:</strong>
{{with $field := field "booking.CardExpMonth" .}}
<select name="{{$field.Name}}">
{{option $field "1" "Jan"}}
{{option $field "2" "Feb"}}
{{option $field "3" "Mar"}}
{{option $field "4" "Apr"}}
{{option $field "5" "May"}}
{{option $field "6" "Jun"}}
{{option $field "7" "Jul"}}
{{option $field "8" "Aug"}}
{{option $field "9" "Sep"}}
{{option $field "10" "Oct"}}
{{option $field "11" "Nov"}}
{{option $field "12" "Dec"}}
</select>
{{end}}
{{with $field := field "booking.CardExpYear" .}}
<select name="{{$field.Name}}">
{{option $field "2008" "2008"}}
{{option $field "2009" "2009"}}
{{option $field "2010" "2010"}}
{{option $field "2011" "2011"}}
{{option $field "2012" "2012"}}
</select>
{{end}}
</p>
<p class="buttons">
<input type="submit" value="Proceed">
<a href="{{url "Hotels.Show" .hotel.HotelId}}">Cancel</a>
</p>
</form>
<script type="text/javascript" charset="utf-8">
$(function() {
$(".datepicker").datepicker({dateFormat: 'yy-mm-dd'});
});
</script>
{{template "footer.html" .}}

View File

@@ -0,0 +1,58 @@
{{template "header.html" .}}
<h1>Confirm hotel booking</h1>
<form method="POST" action="{{url "Hotels.ConfirmBooking" .hotel.HotelId}}">
<p>
<strong>Name:</strong> {{raw .hotel.Name}}
</p>
<p>
<strong>Address:</strong> {{.hotel.Address}}
</p>
<p>
<strong>City:</strong> {{.hotel.City}}
</p>
<p>
<strong>State:</strong> {{.hotel.State}}
</p>
<p>
<strong>Zip:</strong> {{.hotel.Zip}}
</p>
<p>
<strong>Country:</strong> {{.hotel.Country}}
</p>
<p>
<strong>Nightly rate:</strong> {{.hotel.Price}}
</p>
<p>
<strong>Beds:</strong> {{.booking.Beds}}
<input type="hidden" name="booking.Beds" value="{{.booking.Beds}}">
</p>
<p>
<strong>Total:</strong> {{.booking.Total}} {{/* .formatCurrency('USD') */}}
</p>
<p>
<strong>Check in date:</strong> {{.booking.CheckInDate.Format "2006-01-02"}}
<input type="hidden" name="booking.CheckInDate" value="{{.booking.CheckInDate.Format "2006-01-02"}}">
</p>
<p>
<strong>Check out date:</strong> {{.booking.CheckOutDate.Format "2006-01-02"}}
<input type="hidden" name="booking.CheckOutDate" value="{{.booking.CheckOutDate.Format "2006-01-02"}}">
</p>
<p>
<strong>Credit card #:</strong> {{.booking.CardNumber}}
<input type="hidden" name="booking.CardNumber" value="{{.booking.CardNumber}}">
<input type="hidden" name="booking.NameOnCard" value="{{.booking.NameOnCard}}">
<input type="hidden" name="booking.CardExpMonth" value="{{.booking.CardExpMonth}}">
<input type="hidden" name="booking.CardExpYear" value="{{.booking.CardExpYear}}">
<input type="hidden" name="booking.Smoking" value="{{.booking.Smoking}}">
</p>
<p class="buttons">
<input type="submit" value="Confirm" name="confirm">
<input type="submit" value="Revise" name="revise">
<a href="{{url "Hotels.Show" .hotel.HotelId}}">Cancel</a>
</p>
</form>
{{template "footer.html" .}}

View File

@@ -0,0 +1,111 @@
{{set . "title" "Search"}}
{{template "header.html" .}}
<h1>Search Hotels</h1>
<p>
<input type="text" id="search" size="30">
<input type="submit" id="submit" value="Find Hotels">
<br>
Maximum results:
<select id="size">
<option value="5">5</option>
<option value="10">10</option>
<option value="20">20</option>
</select>
</p>
<div id="result">
</div>
<script type="text/javascript" charset="utf-8">
// Rebuild state
$('#search').val(sessvars.search)
if(sessvars.page == undefined) {
sessvars.page = 1
}
if(sessvars.size == undefined) {
sessvars.size = 10
}
$('#size option[value='+sessvars.size+']').attr('selected', 'true')
// Search function
var search = function() {
sessvars.search = $('#search').val()
sessvars.size = $('#size').val()
$.get("/hotels/list", {
"search": sessvars.search,
"size": sessvars.size,
"page": sessvars.page
}, function(data) {
$('#result').html(data)
$('#content').css('visibility', 'visible')
})
}
// Events handler
$('#submit').click(function() {
sessvars.page = 1
search()
})
$('#search').keyup(function() {
sessvars.page = 1
search()
})
$('#nextPage').live('click', function(e) {
sessvars.page = $(this).attr('href')
e.preventDefault()
search()
})
// Init
if(sessvars.search != undefined) {
$('#content').css('visibility', 'hidden')
search()
}
</script>
<h1>Current Hotel Bookings</h1>
{{if not .bookings}}
<p>
No Bookings Found
</p>
{{else}}
<table>
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City, State</th>
<th>Check in</th>
<th>Check out</th>
<th>Confirmation number</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{{range .bookings}}
<tr>
<td>{{.Hotel.Name}}</td>
<td>{{.Hotel.Address}}</td>
<td>{{.Hotel.City}}, {{.Hotel.State}}, {{.Hotel.Country}}</td>
<td>{{.CheckInDate.Format "2006-01-02"}}</td>
<td>{{.CheckOutDate.Format "2006-01-02"}}</td>
<td>{{raw .BookingId}}</td> <!-- not caught because it is inside a range and no parsing is done -->
<td>
<form id="d{{.BookingId}}" method="POST" action="/bookings/{{.BookingId}}/cancel">
<a href="javascript:document.getElementById('d{{.BookingId}}').submit();">Cancel</a>
</form>
</td>
</tr>
{{end}}
</tbody>
</table>
{{end}}
{{template "footer.html" .}}

View File

@@ -0,0 +1,34 @@
{{if .hotels}}
<table>
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City, State</th>
<th width="8%">Zip</th>
<th width="13%">Action</th>
</tr>
</thead>
<tbody>
{{range .hotels}}
<tr>
<td>{{.Name}}</td>
<td>{{.Address}}</td>
<td>{{.City}}, {{.State}}, {{.Country}}</td>
<td>{{.Zip}}</td>
<td>
<a href="{{url "Hotels.Show" .HotelId}}">View Hotel</a>
</td>
</tr>
{{end}}
</tbody>
</table>
<p>
<a id="nextPage" href="{{.nextPage}}">More results</a>
</p>
{{else}}
<p>
No more results
</p>
{{end}}

View File

@@ -0,0 +1,27 @@
{{set . "title" "Settings"}}
{{template "header.html" .}}
<h1>Change your password</h1>
<form method="POST" action="{{url "Hotels.SaveSettings"}}">
{{with $field := field "password" .}}
<p class="{{$field.ErrorClass}}">
<strong>Password:</strong>
<input type="password" name="{{$field.Name}}" size="16"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "verifyPassword" .}}
<p class="{{$field.ErrorClass}}">
<strong>Verify password:</strong>
<input type="password" name="{{$field.Name}}" size="16"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
<p class="buttons">
<input type="submit" value="Save"> <a href="{{url "Hotels.Index"}}">Cancel</a>
</p>
</form>
{{template "footer.html" .}}

View File

@@ -0,0 +1,37 @@
{{template "header.html" .}}
<h1>View hotel</h1>
{{with .hotel}}
<form action="{{url "Hotels.Book" .HotelId}}">
<p>
<strong>Name:</strong> {{.Name}}
</p>
<p>
<strong>Address:</strong> {{.Address}}
</p>
<p>
<strong>City:</strong> {{.City}}
</p>
<p>
<strong>State:</strong> {{.State}}
</p>
<p>
<strong>Zip:</strong> {{.Zip}}
</p>
<p>
<strong>Country:</strong> {{.Country}}
</p>
<p>
<strong>Nightly rate:</strong> {{.Price}}
</p>
<p class="buttons">
<input type="submit" value="Book Hotel">
<a href="{{url "Hotels.Index"}}">Back to search</a>
</p>
</form>
{{end}}
{{template "footer.html" .}}

View File

@@ -0,0 +1,32 @@
{{set . "title" "Home"}}
{{template "header.html" .}}
<div id="login">
(try with demo/demo)
<form action="{{url "Application.Login"}}" id="formLogin" method="POST">
<p class="field">
<label>Login Name:</label>
<input type="text" name="username" size="19" value="{{.flash.username}}" />
</p>
<p class="field">
<label>Password:</label>
<input type="password" name="password" size="19"/>
</p>
<p class="field">
<label>Remember:</label>
<input type="checkbox" name="remember" value="true"/>
</p>
<p class="buttons">
<input type="submit" value="Account login" />
</p>
</form>
<p>
<a href="{{url "Application.Register"}}">Register New User</a>
</p>
</div>
{{template "footer.html" .}}

View File

@@ -0,0 +1,37 @@
{{set . "title" "Register"}}
{{template "header.html" .}}
<h1>Register:</h1>
<form action="{{url "Application.SaveUser"}}" method="POST">
{{with $field := field "user.Username" .}}
<p class="{{$field.ErrorClass}}">
<strong>Username:</strong>
<input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "user.Name" .}}
<p class="{{$field.ErrorClass}}">
<strong>Real name:</strong> <input type="text" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "user.Password" .}}
<p class="{{$field.ErrorClass}}">
<strong>Password:</strong> <input type="password" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
{{with $field := field "verifyPassword" .}}
<p class="{{$field.ErrorClass}}">
<strong>Verify password:</strong> <input type="password" name="{{$field.Name}}" size="16" value="{{$field.Flash}}"> *
<span class="error">{{$field.Error}}</span>
</p>
{{end}}
<p class="buttons">
<input type="submit" value="Register"> <a href="{{url "Application.Index"}}">Cancel</a>
</p>
</form>
{{template "footer.html" .}}

View File

@@ -0,0 +1,8 @@
</div>
<div id="footer">
Created with the <a href="http://github.com/revel/revel">Revel framework</a> and really inspirated from the booking sample application provided by <a href="http://www.playframework.org">play framework</a>, which was really inspired by the booking sample application provided by the <a href="http://seamframework.org/">seam framework</a>.
</div>
</body>
</html>

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.title}}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" media="screen" href="/public/css/main.css">
{{range .moreStyles}}
<link rel="stylesheet" type="text/css" href="/public/{{.}}">
{{end}}
<script src="/public/js/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="/public/js/sessvars.js" type="text/javascript" charset="utf-8"></script>
{{range .moreScripts}}
<script src="/public/{{.}}" type="text/javascript" charset="utf-8"></script>
{{end}}
</head>
<body>
<div id="header">
<h1>revel framework booking demo</h1>
{{if .user}}
<div id="options">
Connected as {{ (session "fulluser" .).Username }}
|
<a href="{{url "Hotels.Index"}}">Search</a>
|
<a href="{{url "Hotels.Settings"}}">Settings</a>
|
<a href="{{url "Application.Logout"}}">Logout</a>
</div>
{{end}}
</div>
<div id="content">
{{if .flash.error}}
<p class="fError">
<strong>{{.flash.error}}</strong>
</p>
{{end}}
{{if .flash.success}}
<p class="fSuccess">
<strong>{{.flash.success}}</strong>
</p>
{{end}}

View File

@@ -3,11 +3,7 @@ module codeql-go-tests/frameworks/Revel
go 1.14
require (
github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/revel/config v1.0.0 // indirect
github.com/revel/modules v1.0.0
github.com/revel/revel v1.0.0
golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
)

View File

@@ -0,0 +1,47 @@
import go
import TestUtilities.InlineExpectationsTest
class Sink extends DataFlow::Node {
Sink() {
exists(DataFlow::CallNode c | c.getTarget().getName() = "sink" | this = c.getAnArgument())
}
}
class TestConfig extends TaintTracking::Configuration {
TestConfig() { this = "testconfig" }
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
}
class MissingDataFlowTest extends InlineExpectationsTest {
MissingDataFlowTest() { this = "MissingDataFlow" }
override string getARelevantTag() { result = "noflow" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
tag = "noflow" and
value = "" and
exists(Sink sink |
not any(TestConfig c).hasFlow(_, sink) and
sink.hasLocationInfo(file, line, _, _, _) and
element = sink.toString()
)
}
}
class HttpResponseBodyTest extends InlineExpectationsTest {
HttpResponseBodyTest() { this = "HttpResponseBodyTest" }
override string getARelevantTag() { result = "responsebody" }
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
tag = "responsebody" and
exists(HTTP::ResponseBody rb |
rb.hasLocationInfo(file, line, _, _, _) and
element = rb.toString() and
value = rb.toString()
)
}
}

View File

@@ -0,0 +1,18 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/revel/modules/orm/gorp/app/controllers, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/revel/modules/orm/gorp/app/controllers (exports: Controller; functions: )
// Package controllers is a stub of github.com/revel/modules/orm/gorp/app/controllers, generated by depstubber.
package gorpController
import (
revel "github.com/revel/revel"
)
type Controller struct {
*revel.Controller
Txn interface{}
Db interface{}
}

View File

@@ -0,0 +1,114 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/revel/revel/logger, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/revel/revel/logger (exports: MultiLogger,LogOptions,CompositeMultiHandler; functions: LogFunctionMap)
// Package logger is a stub of github.com/revel/revel/logger, generated by depstubber.
package logger
import (
fmt "fmt"
io "io"
time "time"
)
type CallStack interface {
Format(_ fmt.State, _ int32)
}
type CompositeMultiHandler struct {
DebugHandler LogHandler
InfoHandler LogHandler
WarnHandler LogHandler
ErrorHandler LogHandler
CriticalHandler LogHandler
}
func (_ *CompositeMultiHandler) Disable(_ ...LogLevel) {}
func (_ *CompositeMultiHandler) Log(_ *Record) error {
return nil
}
func (_ *CompositeMultiHandler) SetHandler(_ LogHandler, _ bool, _ LogLevel) {}
func (_ *CompositeMultiHandler) SetHandlers(_ LogHandler, _ *LogOptions) {}
func (_ *CompositeMultiHandler) SetJson(_ io.Writer, _ *LogOptions) {}
func (_ *CompositeMultiHandler) SetJsonFile(_ string, _ *LogOptions) {}
func (_ *CompositeMultiHandler) SetTerminal(_ io.Writer, _ *LogOptions) {}
func (_ *CompositeMultiHandler) SetTerminalFile(_ string, _ *LogOptions) {}
type ContextMap map[string]interface{}
func (_ ContextMap) Add(_ string, _ interface{}) {}
func (_ ContextMap) StringMap() map[string]string {
return nil
}
var LogFunctionMap map[string]func(*CompositeMultiHandler, *LogOptions) = nil
type LogHandler interface {
Log(_ *Record) error
}
type LogLevel int
type LogOptions struct {
Ctx interface{}
ReplaceExistingHandler bool
HandlerWrap ParentLogHandler
Levels []LogLevel
ExtendedOptions map[string]interface{}
}
func (_ *LogOptions) GetBoolDefault(_ string, _ bool) bool {
return false
}
func (_ *LogOptions) GetIntDefault(_ string, _ int) int {
return 0
}
func (_ *LogOptions) GetStringDefault(_ string, _ string) string {
return ""
}
func (_ *LogOptions) SetExtendedOptions(_ ...interface{}) {}
type MultiLogger interface {
Crit(_ string, _ ...interface{})
Critf(_ string, _ ...interface{})
Debug(_ string, _ ...interface{})
Debugf(_ string, _ ...interface{})
Error(_ string, _ ...interface{})
Errorf(_ string, _ ...interface{})
Fatal(_ string, _ ...interface{})
Fatalf(_ string, _ ...interface{})
Info(_ string, _ ...interface{})
Infof(_ string, _ ...interface{})
New(_ ...interface{}) MultiLogger
Panic(_ string, _ ...interface{})
Panicf(_ string, _ ...interface{})
SetHandler(_ LogHandler)
SetStackDepth(_ int) MultiLogger
Warn(_ string, _ ...interface{})
Warnf(_ string, _ ...interface{})
}
type ParentLogHandler interface {
SetChild(_ LogHandler) LogHandler
}
type Record struct {
Message string
Time time.Time
Level LogLevel
Call CallStack
Context ContextMap
}

View File

@@ -0,0 +1,62 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/revel/revel/session, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/revel/revel/session (exports: Session; functions: )
// Package session is a stub of github.com/revel/revel/session, generated by depstubber.
package session
import (
time "time"
)
type Session map[string]interface{}
func (_ Session) Del(_ string) {}
func (_ Session) Empty() bool {
return false
}
func (_ Session) Get(_ string) (interface{}, error) {
return nil, nil
}
func (_ Session) GetDefault(_ string, _ interface{}, _ interface{}) interface{} {
return nil
}
func (_ Session) GetExpiration(_ time.Duration) time.Time {
return time.Time{}
}
func (_ Session) GetInto(_ string, _ interface{}, _ bool) (interface{}, error) {
return nil, nil
}
func (_ Session) GetProperty(_ string, _ interface{}) (interface{}, error) {
return nil, nil
}
func (_ Session) ID() string {
return ""
}
func (_ Session) Load(_ map[string]string) {}
func (_ Session) Serialize() map[string]string {
return nil
}
func (_ Session) SessionTimeoutExpiredOrMissing() bool {
return false
}
func (_ Session) Set(_ string, _ interface{}) error {
return nil
}
func (_ Session) SetDefaultExpiration() {}
func (_ Session) SetNoExpiration() {}

View File

@@ -9,6 +9,8 @@ package revel
import (
context "context"
logger "github.com/revel/revel/logger"
session "github.com/revel/revel/session"
io "io"
multipart "mime/multipart"
http "net/http"
@@ -53,6 +55,12 @@ func (_ *ActionDefinition) String() string {
return ""
}
func ActionInvoker(_ *Controller, _ []Filter) {}
func AddHTTPMux(_ string, _ interface{}) {}
func AddInitEventHandler(_ EventHandler) {}
type ContentDisposition string
var (
@@ -73,12 +81,12 @@ type Controller struct {
Response *Response
Result Result
Flash Flash
Session interface{}
Session session.Session
Params *Params
Args map[string]interface{}
ViewArgs map[string]interface{}
Validation *Validation
Log interface{}
Log logger.MultiLogger
}
func (_ *Controller) Destroy() {}
@@ -230,6 +238,43 @@ func (_ *Error) Error() string {
func (_ *Error) SetLink(_ string) {}
type Event int
const (
TEMPLATE_REFRESH_REQUESTED Event = iota
TEMPLATE_REFRESH_COMPLETED
REVEL_BEFORE_MODULES_LOADED
REVEL_AFTER_MODULES_LOADED
ENGINE_BEFORE_INITIALIZED
ENGINE_STARTED
ENGINE_SHUTDOWN_REQUEST
ENGINE_SHUTDOWN
ROUTE_REFRESH_REQUESTED
ROUTE_REFRESH_COMPLETED
REVEL_FAILURE
)
type EventHandler func(typeOf Event, value interface{}) (responseOf EventResponse)
type EventResponse int
type Filter func(c *Controller, filterChain []Filter)
var Filters = []Filter{}
var (
PanicFilter Filter = nil
RouterFilter Filter = nil
FilterConfiguringFilter Filter = nil
ParamsFilter Filter = nil
SessionFilter Filter = nil
FlashFilter Filter = nil
ValidationFilter Filter = nil
I18nFilter Filter = nil
InterceptorFilter Filter = nil
CompressFilter Filter = nil
)
type Flash struct {
Data map[string]string
Out map[string]string
@@ -241,6 +286,34 @@ func (_ Flash) Success(_ string, _ ...interface{}) {}
var HTTP_QUERY int = 0
func InterceptMethod(intc InterceptorMethod, when When) {}
type InterceptorMethod interface{}
type Match struct {
Regexp *regexp.Regexp
}
func (_ Match) DefaultMessage() string {
return ""
}
func (_ Match) IsSatisfied(obj interface{}) bool {
return false
}
type MaxSize struct {
Max int
}
func (_ MaxSize) DefaultMessage() string {
return ""
}
func (_ MaxSize) IsSatisfied(obj interface{}) bool {
return false
}
type MethodArg struct {
Name string
Type reflect.Type
@@ -253,6 +326,18 @@ type MethodType struct {
Index int
}
type MinSize struct {
Min int
}
func (_ MinSize) DefaultMessage() string {
return ""
}
func (_ MinSize) IsSatisfied(obj interface{}) bool {
return false
}
type Module struct {
Name string
ImportPath string
@@ -276,6 +361,8 @@ type MultipartForm struct {
Value url.Values
}
func OnAppStart(_ func(), _ ...int) {}
type OutResponse struct {
Server ServerResponse
}
@@ -398,6 +485,16 @@ func (_ *Request) UserAgent() string {
return ""
}
type Required struct{}
func (_ Required) DefaultMessage() string {
return ""
}
func (_ Required) IsSatisfied(obj interface{}) bool {
return false
}
type Response struct {
Status int
ContentType string
@@ -695,3 +792,12 @@ type Validator interface {
DefaultMessage() string
IsSatisfied(_ interface{}) bool
}
type When int
const (
BEFORE When = iota
AFTER
PANIC
FINALLY
)

View File

@@ -1,21 +1,9 @@
# github.com/github/depstubber v0.0.0-20200916130315-f3217697abd4
## explicit
github.com/github/depstubber
# github.com/go-stack/stack v1.8.0
## explicit
github.com/go-stack/stack
# github.com/mattn/go-colorable v0.1.7
## explicit
github.com/mattn/go-colorable
# github.com/revel/config v1.0.0
## explicit
github.com/revel/config
# github.com/revel/modules v1.0.0
## explicit
github.com/revel/modules
# github.com/revel/revel v1.0.0
## explicit
github.com/revel/revel
# golang.org/x/net v0.0.0-20200904194848-62affa334b73
## explicit
golang.org/x/net

View File

@@ -0,0 +1,2 @@
{{raw .Foo}}
{{.Bar}}

View File

@@ -53,14 +53,14 @@ nodes
| test.go:36:15:36:44 | type conversion | semmle.label | type conversion |
| test.go:36:22:36:38 | call to Token : Token | semmle.label | call to Token : Token |
#select
| test.go:14:15:14:55 | type conversion | test.go:10:15:10:42 | call to Cookie : tuple type | test.go:14:15:14:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:10:15:10:42 | call to Cookie | user-provided value |
| test.go:17:15:17:31 | type conversion | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:17:15:17:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value |
| test.go:20:15:20:32 | type conversion | test.go:19:36:19:47 | selection of Body : ReadCloser | test.go:20:15:20:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:19:36:19:47 | selection of Body | user-provided value |
| test.go:23:15:23:35 | type conversion | test.go:22:33:22:44 | selection of Body : ReadCloser | test.go:23:15:23:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:33:22:44 | selection of Body | user-provided value |
| test.go:26:15:26:36 | type conversion | test.go:25:45:25:56 | selection of Body : ReadCloser | test.go:26:15:26:36 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:25:45:25:56 | selection of Body | user-provided value |
| test.go:28:22:28:25 | node | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:28:22:28:25 | node | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value |
| test.go:31:15:31:34 | call to Buffered | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:31:15:31:34 | call to Buffered | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value |
| test.go:32:15:32:29 | call to Raw | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:32:15:32:29 | call to Raw | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value |
| test.go:34:15:34:19 | value | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:34:15:34:19 | value | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value |
| test.go:35:15:35:30 | call to Text | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:35:15:35:30 | call to Text | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value |
| test.go:36:15:36:44 | type conversion | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:36:15:36:44 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value |
| test.go:14:15:14:55 | type conversion | test.go:10:15:10:42 | call to Cookie : tuple type | test.go:14:15:14:55 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:10:15:10:42 | call to Cookie | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:17:15:17:31 | type conversion | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:17:15:17:31 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:20:15:20:32 | type conversion | test.go:19:36:19:47 | selection of Body : ReadCloser | test.go:20:15:20:32 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:19:36:19:47 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:23:15:23:35 | type conversion | test.go:22:33:22:44 | selection of Body : ReadCloser | test.go:23:15:23:35 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:22:33:22:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:26:15:26:36 | type conversion | test.go:25:45:25:56 | selection of Body : ReadCloser | test.go:26:15:26:36 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:25:45:25:56 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:28:22:28:25 | node | test.go:16:24:16:35 | selection of Body : ReadCloser | test.go:28:22:28:25 | node | Cross-site scripting vulnerability due to $@. | test.go:16:24:16:35 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:31:15:31:34 | call to Buffered | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:31:15:31:34 | call to Buffered | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:32:15:32:29 | call to Raw | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:32:15:32:29 | call to Raw | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:34:15:34:19 | value | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:34:15:34:19 | value | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:35:15:35:30 | call to Text | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:35:15:35:30 | call to Text | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |
| test.go:36:15:36:44 | type conversion | test.go:30:33:30:44 | selection of Body : ReadCloser | test.go:36:15:36:44 | type conversion | Cross-site scripting vulnerability due to $@. | test.go:30:33:30:44 | selection of Body | user-provided value | test.go:0:0:0:0 | test.go | |

View File

@@ -46,18 +46,18 @@ nodes
| websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | semmle.label | ... := ...[1] : slice type |
| websocketXss.go:55:24:55:31 | gorilla3 | semmle.label | gorilla3 |
#select
| ReflectedXss.go:15:44:15:51 | username | ReflectedXss.go:12:15:12:20 | selection of Form : Values | ReflectedXss.go:15:44:15:51 | username | Cross-site scripting vulnerability due to $@. | ReflectedXss.go:12:15:12:20 | selection of Form | user-provided value |
| contenttype.go:17:11:17:22 | type conversion | contenttype.go:11:11:11:16 | selection of Form : Values | contenttype.go:17:11:17:22 | type conversion | Cross-site scripting vulnerability due to $@. | contenttype.go:11:11:11:16 | selection of Form | user-provided value |
| contenttype.go:53:34:53:37 | data | contenttype.go:49:11:49:16 | selection of Form : Values | contenttype.go:53:34:53:37 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:49:11:49:16 | selection of Form | user-provided value |
| contenttype.go:64:52:64:55 | data | contenttype.go:63:10:63:28 | call to FormValue : string | contenttype.go:64:52:64:55 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:63:10:63:28 | call to FormValue | user-provided value |
| contenttype.go:79:11:79:14 | data | contenttype.go:73:10:73:28 | call to FormValue : string | contenttype.go:79:11:79:14 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:73:10:73:28 | call to FormValue | user-provided value |
| contenttype.go:91:4:91:7 | data | contenttype.go:88:10:88:28 | call to FormValue : string | contenttype.go:91:4:91:7 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:88:10:88:28 | call to FormValue | user-provided value |
| contenttype.go:114:50:114:53 | data | contenttype.go:113:10:113:28 | call to FormValue : string | contenttype.go:114:50:114:53 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:113:10:113:28 | call to FormValue | user-provided value |
| tst.go:18:12:18:39 | type conversion | tst.go:14:15:14:20 | selection of Form : Values | tst.go:18:12:18:39 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:14:15:14:20 | selection of Form | user-provided value |
| tst.go:53:12:53:26 | type conversion | tst.go:48:14:48:19 | selection of Form : Values | tst.go:53:12:53:26 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:48:14:48:19 | selection of Form | user-provided value |
| websocketXss.go:32:24:32:27 | xnet | websocketXss.go:30:7:30:10 | definition of xnet : slice type | websocketXss.go:32:24:32:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:30:7:30:10 | definition of xnet | user-provided value |
| websocketXss.go:36:24:36:28 | xnet2 | websocketXss.go:34:3:34:7 | definition of xnet2 : slice type | websocketXss.go:36:24:36:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:34:3:34:7 | definition of xnet2 | user-provided value |
| websocketXss.go:41:24:41:29 | nhooyr | websocketXss.go:40:3:40:40 | ... := ...[1] : slice type | websocketXss.go:41:24:41:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:40:3:40:40 | ... := ...[1] | user-provided value |
| websocketXss.go:48:24:48:33 | gorillaMsg | websocketXss.go:46:7:46:16 | definition of gorillaMsg : slice type | websocketXss.go:48:24:48:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:46:7:46:16 | definition of gorillaMsg | user-provided value |
| websocketXss.go:52:24:52:31 | gorilla2 | websocketXss.go:50:3:50:10 | definition of gorilla2 : slice type | websocketXss.go:52:24:52:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:50:3:50:10 | definition of gorilla2 | user-provided value |
| websocketXss.go:55:24:55:31 | gorilla3 | websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | websocketXss.go:55:24:55:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:54:3:54:38 | ... := ...[1] | user-provided value |
| ReflectedXss.go:15:44:15:51 | username | ReflectedXss.go:12:15:12:20 | selection of Form : Values | ReflectedXss.go:15:44:15:51 | username | Cross-site scripting vulnerability due to $@. | ReflectedXss.go:12:15:12:20 | selection of Form | user-provided value | ReflectedXss.go:0:0:0:0 | ReflectedXss.go | |
| contenttype.go:17:11:17:22 | type conversion | contenttype.go:11:11:11:16 | selection of Form : Values | contenttype.go:17:11:17:22 | type conversion | Cross-site scripting vulnerability due to $@. | contenttype.go:11:11:11:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| contenttype.go:53:34:53:37 | data | contenttype.go:49:11:49:16 | selection of Form : Values | contenttype.go:53:34:53:37 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:49:11:49:16 | selection of Form | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| contenttype.go:64:52:64:55 | data | contenttype.go:63:10:63:28 | call to FormValue : string | contenttype.go:64:52:64:55 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:63:10:63:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| contenttype.go:79:11:79:14 | data | contenttype.go:73:10:73:28 | call to FormValue : string | contenttype.go:79:11:79:14 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:73:10:73:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| contenttype.go:91:4:91:7 | data | contenttype.go:88:10:88:28 | call to FormValue : string | contenttype.go:91:4:91:7 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:88:10:88:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| contenttype.go:114:50:114:53 | data | contenttype.go:113:10:113:28 | call to FormValue : string | contenttype.go:114:50:114:53 | data | Cross-site scripting vulnerability due to $@. | contenttype.go:113:10:113:28 | call to FormValue | user-provided value | contenttype.go:0:0:0:0 | contenttype.go | |
| tst.go:18:12:18:39 | type conversion | tst.go:14:15:14:20 | selection of Form : Values | tst.go:18:12:18:39 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:14:15:14:20 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | |
| tst.go:53:12:53:26 | type conversion | tst.go:48:14:48:19 | selection of Form : Values | tst.go:53:12:53:26 | type conversion | Cross-site scripting vulnerability due to $@. | tst.go:48:14:48:19 | selection of Form | user-provided value | tst.go:0:0:0:0 | tst.go | |
| websocketXss.go:32:24:32:27 | xnet | websocketXss.go:30:7:30:10 | definition of xnet : slice type | websocketXss.go:32:24:32:27 | xnet | Cross-site scripting vulnerability due to $@. | websocketXss.go:30:7:30:10 | definition of xnet | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |
| websocketXss.go:36:24:36:28 | xnet2 | websocketXss.go:34:3:34:7 | definition of xnet2 : slice type | websocketXss.go:36:24:36:28 | xnet2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:34:3:34:7 | definition of xnet2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |
| websocketXss.go:41:24:41:29 | nhooyr | websocketXss.go:40:3:40:40 | ... := ...[1] : slice type | websocketXss.go:41:24:41:29 | nhooyr | Cross-site scripting vulnerability due to $@. | websocketXss.go:40:3:40:40 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |
| websocketXss.go:48:24:48:33 | gorillaMsg | websocketXss.go:46:7:46:16 | definition of gorillaMsg : slice type | websocketXss.go:48:24:48:33 | gorillaMsg | Cross-site scripting vulnerability due to $@. | websocketXss.go:46:7:46:16 | definition of gorillaMsg | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |
| websocketXss.go:52:24:52:31 | gorilla2 | websocketXss.go:50:3:50:10 | definition of gorilla2 : slice type | websocketXss.go:52:24:52:31 | gorilla2 | Cross-site scripting vulnerability due to $@. | websocketXss.go:50:3:50:10 | definition of gorilla2 | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |
| websocketXss.go:55:24:55:31 | gorilla3 | websocketXss.go:54:3:54:38 | ... := ...[1] : slice type | websocketXss.go:55:24:55:31 | gorilla3 | Cross-site scripting vulnerability due to $@. | websocketXss.go:54:3:54:38 | ... := ...[1] | user-provided value | websocketXss.go:0:0:0:0 | websocketXss.go | |

View File

@@ -0,0 +1,510 @@
/** Auto-generated dbscheme; do not edit. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
/*
* XML Files
*/
xmlEncoding(
unique int id: @file ref,
string encoding: string ref
);
xmlDTDs(
unique int id: @xmldtd,
string root: string ref,
string publicId: string ref,
string systemId: string ref,
int fileid: @file ref
);
xmlElements(
unique int id: @xmlelement,
string name: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int fileid: @file ref
);
xmlAttrs(
unique int id: @xmlattribute,
int elementid: @xmlelement ref,
string name: string ref,
string value: string ref,
int idx: int ref,
int fileid: @file ref
);
xmlNs(
int id: @xmlnamespace,
string prefixName: string ref,
string URI: string ref,
int fileid: @file ref
);
xmlHasNs(
int elementId: @xmlnamespaceable ref,
int nsId: @xmlnamespace ref,
int fileid: @file ref
);
xmlComments(
unique int id: @xmlcomment,
string text: string ref,
int parentid: @xmlparent ref,
int fileid: @file ref
);
xmlChars(
unique int id: @xmlcharacters,
string text: string ref,
int parentid: @xmlparent ref,
int idx: int ref,
int isCDATA: int ref,
int fileid: @file ref
);
@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;
xmllocations(
int xmlElement: @xmllocatable ref,
int location: @location_default ref
);
@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref, string simple: string ref, string ext: string ref, int fromSource: int ref);
folders(unique int id: @folder, string name: string ref, string simple: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @namedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int named: @namedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
@container = @file | @folder;
@locatable = @xmllocatable | @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @sliceexpr
| 14 = @typeassertexpr
| 15 = @callorconversionexpr
| 16 = @starexpr
| 17 = @keyvalueexpr
| 18 = @arraytypeexpr
| 19 = @structtypeexpr
| 20 = @functypeexpr
| 21 = @interfacetypeexpr
| 22 = @maptypeexpr
| 23 = @plusexpr
| 24 = @minusexpr
| 25 = @notexpr
| 26 = @complementexpr
| 27 = @derefexpr
| 28 = @addressexpr
| 29 = @arrowexpr
| 30 = @lorexpr
| 31 = @landexpr
| 32 = @eqlexpr
| 33 = @neqexpr
| 34 = @lssexpr
| 35 = @leqexpr
| 36 = @gtrexpr
| 37 = @geqexpr
| 38 = @addexpr
| 39 = @subexpr
| 40 = @orexpr
| 41 = @xorexpr
| 42 = @mulexpr
| 43 = @quoexpr
| 44 = @remexpr
| 45 = @shlexpr
| 46 = @shrexpr
| 47 = @andexpr
| 48 = @andnotexpr
| 49 = @sendchantypeexpr
| 50 = @recvchantypeexpr
| 51 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @arraytype
| 27 = @slicetype
| 28 = @structtype
| 29 = @pointertype
| 30 = @interfacetype
| 31 = @tupletype
| 32 = @signaturetype
| 33 = @maptype
| 34 = @sendchantype
| 35 = @recvchantype
| 36 = @sendrcvchantype
| 37 = @namedtype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,436 @@
/** Auto-generated dbscheme; do not edit. */
/** Duplicate code **/
duplicateCode(
unique int id : @duplication,
varchar(900) relativePath : string ref,
int equivClass : int ref);
similarCode(
unique int id : @similarity,
varchar(900) relativePath : string ref,
int equivClass : int ref);
@duplication_or_similarity = @duplication | @similarity;
tokens(
int id : @duplication_or_similarity ref,
int offset : int ref,
int beginLine : int ref,
int beginColumn : int ref,
int endLine : int ref,
int endColumn : int ref);
/** External data **/
externalData(
int id : @externalDataElement,
varchar(900) path : string ref,
int column: int ref,
varchar(900) value : string ref
);
snapshotDate(unique date snapshotDate : date ref);
sourceLocationPrefix(varchar(900) prefix : string ref);
locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
int endLine: int ref, int endColumn: int ref);
numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
files(unique int id: @file, string name: string ref, string simple: string ref, string ext: string ref, int fromSource: int ref);
folders(unique int id: @folder, string name: string ref, string simple: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
has_location(unique int locatable: @locatable ref, int location: @location ref);
#keyset[parent, idx]
comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
#keyset[parent, idx]
exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
#keyset[parent, idx]
stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
#keyset[parent, idx]
decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
#keyset[parent, idx]
specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
scopes(unique int id: @scope, int kind: int ref);
scopenesting(unique int inner: @scope ref, int outer: @scope ref);
scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
objects(unique int id: @object, int kind: int ref, string name: string ref);
objectscopes(unique int object: @object ref, int scope: @scope ref);
objecttypes(unique int object: @object ref, int tp: @type ref);
methodreceivers(unique int method: @object ref, int receiver: @object ref);
fieldstructs(unique int field: @object ref, int struct: @structtype ref);
methodhosts(int method: @object ref, int host: @namedtype ref);
defs(int ident: @ident ref, int object: @object ref);
uses(int ident: @ident ref, int object: @object ref);
types(unique int id: @type, int kind: int ref);
type_of(unique int expr: @expr ref, int tp: @type ref);
typename(unique int tp: @type ref, string name: string ref);
key_type(unique int map: @maptype ref, int tp: @type ref);
element_type(unique int container: @containertype ref, int tp: @type ref);
base_type(unique int ptr: @pointertype ref, int tp: @type ref);
underlying_type(unique int named: @namedtype ref, int tp: @type ref);
#keyset[parent, index]
component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
array_length(unique int tp: @arraytype ref, string len: string ref);
type_objects(unique int tp: @type ref, int object: @object ref);
packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
#keyset[parent, idx]
modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
#keyset[parent, idx]
modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
#keyset[package, idx]
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
has_ellipsis(int id: @callorconversionexpr ref);
@container = @file | @folder;
@locatable = @node | @localscope;
@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
| @comment_group | @comment;
@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
@modexprparent = @file | @modexpr;
@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
@stmtparent = @funcdef | @stmt | @decl;
@declparent = @file | @declstmt;
@funcdef = @funclit | @funcdecl;
@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
@location = @location_default;
@sourceline = @locatable;
case @comment.kind of
0 = @slashslashcomment
| 1 = @slashstarcomment;
case @expr.kind of
0 = @badexpr
| 1 = @ident
| 2 = @ellipsis
| 3 = @intlit
| 4 = @floatlit
| 5 = @imaglit
| 6 = @charlit
| 7 = @stringlit
| 8 = @funclit
| 9 = @compositelit
| 10 = @parenexpr
| 11 = @selectorexpr
| 12 = @indexexpr
| 13 = @sliceexpr
| 14 = @typeassertexpr
| 15 = @callorconversionexpr
| 16 = @starexpr
| 17 = @keyvalueexpr
| 18 = @arraytypeexpr
| 19 = @structtypeexpr
| 20 = @functypeexpr
| 21 = @interfacetypeexpr
| 22 = @maptypeexpr
| 23 = @plusexpr
| 24 = @minusexpr
| 25 = @notexpr
| 26 = @complementexpr
| 27 = @derefexpr
| 28 = @addressexpr
| 29 = @arrowexpr
| 30 = @lorexpr
| 31 = @landexpr
| 32 = @eqlexpr
| 33 = @neqexpr
| 34 = @lssexpr
| 35 = @leqexpr
| 36 = @gtrexpr
| 37 = @geqexpr
| 38 = @addexpr
| 39 = @subexpr
| 40 = @orexpr
| 41 = @xorexpr
| 42 = @mulexpr
| 43 = @quoexpr
| 44 = @remexpr
| 45 = @shlexpr
| 46 = @shrexpr
| 47 = @andexpr
| 48 = @andnotexpr
| 49 = @sendchantypeexpr
| 50 = @recvchantypeexpr
| 51 = @sendrcvchantypeexpr;
@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
@logicalunaryexpr = @notexpr;
@bitwiseunaryexpr = @complementexpr;
@arithmeticunaryexpr = @plusexpr | @minusexpr;
@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
@logicalbinaryexpr = @lorexpr | @landexpr;
@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
@shiftexpr = @shlexpr | @shrexpr;
@comparison = @equalitytest | @relationalcomparison;
@equalitytest = @eqlexpr | @neqexpr;
@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
case @stmt.kind of
0 = @badstmt
| 1 = @declstmt
| 2 = @emptystmt
| 3 = @labeledstmt
| 4 = @exprstmt
| 5 = @sendstmt
| 6 = @incstmt
| 7 = @decstmt
| 8 = @gostmt
| 9 = @deferstmt
| 10 = @returnstmt
| 11 = @breakstmt
| 12 = @continuestmt
| 13 = @gotostmt
| 14 = @fallthroughstmt
| 15 = @blockstmt
| 16 = @ifstmt
| 17 = @caseclause
| 18 = @exprswitchstmt
| 19 = @typeswitchstmt
| 20 = @commclause
| 21 = @selectstmt
| 22 = @forstmt
| 23 = @rangestmt
| 24 = @assignstmt
| 25 = @definestmt
| 26 = @addassignstmt
| 27 = @subassignstmt
| 28 = @mulassignstmt
| 29 = @quoassignstmt
| 30 = @remassignstmt
| 31 = @andassignstmt
| 32 = @orassignstmt
| 33 = @xorassignstmt
| 34 = @shlassignstmt
| 35 = @shrassignstmt
| 36 = @andnotassignstmt;
@incdecstmt = @incstmt | @decstmt;
@assignment = @simpleassignstmt | @compoundassignstmt;
@simpleassignstmt = @assignstmt | @definestmt;
@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
| @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
@switchstmt = @exprswitchstmt | @typeswitchstmt;
@loopstmt = @forstmt | @rangestmt;
case @decl.kind of
0 = @baddecl
| 1 = @importdecl
| 2 = @constdecl
| 3 = @typedecl
| 4 = @vardecl
| 5 = @funcdecl;
@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
case @spec.kind of
0 = @importspec
| 1 = @valuespec
| 2 = @typedefspec
| 3 = @aliasspec;
@typespec = @typedefspec | @aliasspec;
case @object.kind of
0 = @pkgobject
| 1 = @decltypeobject
| 2 = @builtintypeobject
| 3 = @declconstobject
| 4 = @builtinconstobject
| 5 = @declvarobject
| 6 = @declfunctionobject
| 7 = @builtinfunctionobject
| 8 = @labelobject;
@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
@typeobject = @decltypeobject | @builtintypeobject;
@valueobject = @constobject | @varobject | @functionobject;
@constobject = @declconstobject | @builtinconstobject;
@varobject = @declvarobject;
@functionobject = @declfunctionobject | @builtinfunctionobject;
case @scope.kind of
0 = @universescope
| 1 = @packagescope
| 2 = @localscope;
case @type.kind of
0 = @invalidtype
| 1 = @boolexprtype
| 2 = @inttype
| 3 = @int8type
| 4 = @int16type
| 5 = @int32type
| 6 = @int64type
| 7 = @uinttype
| 8 = @uint8type
| 9 = @uint16type
| 10 = @uint32type
| 11 = @uint64type
| 12 = @uintptrtype
| 13 = @float32type
| 14 = @float64type
| 15 = @complex64type
| 16 = @complex128type
| 17 = @stringexprtype
| 18 = @unsafepointertype
| 19 = @boolliteraltype
| 20 = @intliteraltype
| 21 = @runeliteraltype
| 22 = @floatliteraltype
| 23 = @complexliteraltype
| 24 = @stringliteraltype
| 25 = @nilliteraltype
| 26 = @arraytype
| 27 = @slicetype
| 28 = @structtype
| 29 = @pointertype
| 30 = @interfacetype
| 31 = @tupletype
| 32 = @signaturetype
| 33 = @maptype
| 34 = @sendchantype
| 35 = @recvchantype
| 36 = @sendrcvchantype
| 37 = @namedtype;
@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
@booltype = @boolexprtype | @boolliteraltype;
@numerictype = @integertype | @floattype | @complextype;
@integertype = @signedintegertype | @unsignedintegertype;
@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
@floattype = @float32type | @float64type | @floatliteraltype;
@complextype = @complex64type | @complex128type | @complexliteraltype;
@stringtype = @stringexprtype | @stringliteraltype;
@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
| @stringliteraltype | @nilliteraltype;
@compositetype = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
@containertype = @arraytype | @slicetype | @maptype | @chantype;
@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
case @modexpr.kind of
0 = @modcommentblock
| 1 = @modline
| 2 = @modlineblock
| 3 = @modlparen
| 4 = @modrparen;
case @error.kind of
0 = @unknownerror
| 1 = @listerror
| 2 = @parseerror
| 3 = @typeerror;

View File

@@ -0,0 +1,2 @@
description: Add XML tables
compatibility: backwards