Compare commits

...

20 Commits

Author SHA1 Message Date
Dave Bartolomeo
a65174af86 Fix path transformer handling of extensionless files 2020-10-06 10:53:19 -04:00
Tom Hvitved
ac370760b4 C#: Construct File::TransformedPathLazy lazily
This avoids calling the path transformer for `GeneratedFile`s.
2020-09-14 11:05:06 +02:00
Tom Hvitved
d6f348ae45 Remove nullness annotations 2020-09-10 15:34:53 +02:00
Tom Hvitved
d1b496d3d3 Address review comments 2020-09-10 15:31:27 +02:00
Tom Hvitved
3f1b3e0c56 C#: Implement support for path transformers 2020-09-10 15:31:17 +02:00
Tom Hvitved
5379690961 C#: Support wild-cards in file patterns
Implements the specification at https://wiki.semmle.com/display/SDmaster/project-layout+format
by compiling file path specifications to regular expressions.
2020-09-10 15:29:35 +02:00
Tom Hvitved
df72141fd1 C#: Rename Layout.Condition to FilePattern and move to separate file 2020-09-10 15:29:27 +02:00
Shati Patel
eaec2d722c Merge pull request #3888 from shati-patel/go-docs
Learning CodeQL: Add new library modeling guide (Go)
2020-07-07 09:54:39 +01:00
Shati Patel
f98491a052 Apply suggestions from code review
Co-authored-by: James Fletcher <42464962+jf205@users.noreply.github.com>
2020-07-06 18:30:01 +01:00
Arthur Baars
f917b9e3cb Merge pull request #3608 from aschackmull/java/backport-switchexpr-cfg-fix
Java: Backport missing CFG edge fix for switch expressions
2020-07-06 11:43:16 +02:00
Shati Patel
45bd492161 Learning CodeQL: Add new library modeling guide (Go) 2020-07-03 08:10:44 +01:00
James Fletcher
d5c6433245 Merge pull request #3849 from asger-semmle/js/vue-support-rc
JS: Add Vue to list of supported frameworks
2020-06-30 15:43:04 +01:00
Asger Feldthaus
472501bd6f JS: Add Vue to list of supported frameworks 2020-06-30 13:47:25 +01:00
semmle-qlci
c2de54f5ca Merge pull request #3685 from shati-patel/ast-go-edits
Approved by felicitymay, owen-mc
2020-06-11 12:43:20 +01:00
Shati Patel
2874050503 CodeQL for Go: Edit AST reference 2020-06-11 10:49:19 +01:00
Max Schaefer
cee248520e Merge pull request #3675 from owen-mc/ast-class-reference-for-go
AST class reference for go
2020-06-11 08:05:41 +01:00
Owen Mansel-Chan
d8900448ec Add references to the AST class reference for go 2020-06-10 17:32:41 +01:00
Owen Mansel-Chan
48ff00832c Add a reference to the AST class reference for go 2020-06-10 17:24:40 +01:00
Owen Mansel-Chan
5b2c0fbb04 AST class reference for go
The master copy of this file is in the codeql-go repository
2020-06-10 16:42:03 +01:00
Anders Schack-Mulligen
a969dbc6ca Java: Fix missing CFG edge for switch expressions. 2020-06-03 10:49:08 +02:00
26 changed files with 1252 additions and 273 deletions

View File

@@ -37,7 +37,7 @@ namespace Semmle.Extraction.CIL
namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(mdReader.GetString(n))); namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(mdReader.GetString(n)));
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace); namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path)); sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));
folders = new CachedFunction<string, Entities.Folder>(path => new Entities.Folder(this, path)); folders = new CachedFunction<PathTransformer.ITransformedPath, Entities.Folder>(path => new Entities.Folder(this, path));
sourceLocations = new CachedFunction<PDB.Location, Entities.PdbSourceLocation>(location => new Entities.PdbSourceLocation(this, location)); sourceLocations = new CachedFunction<PDB.Location, Entities.PdbSourceLocation>(location => new Entities.PdbSourceLocation(this, location));
defaultGenericContext = new EmptyContext(this); defaultGenericContext = new EmptyContext(this);

View File

@@ -5,6 +5,7 @@ using Semmle.Util.Logging;
using System; using System;
using Semmle.Extraction.Entities; using Semmle.Extraction.Entities;
using System.IO; using System.IO;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities namespace Semmle.Extraction.CIL.Entities
{ {
@@ -134,9 +135,12 @@ namespace Semmle.Extraction.CIL.Entities
extracted = false; extracted = false;
try try
{ {
var extractor = new Extractor(false, assemblyPath, logger); var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var project = layout.LookupProjectOrDefault(assemblyPath); var pathTransformer = new PathTransformer(canonicalPathCache);
using (var trapWriter = project.CreateTrapWriter(logger, assemblyPath + ".cil", true, trapCompression)) var extractor = new Extractor(false, assemblyPath, logger, pathTransformer);
var transformedAssemblyPath = pathTransformer.Transform(assemblyPath);
var project = layout.LookupProjectOrDefault(transformedAssemblyPath);
using (var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), true, trapCompression))
{ {
trapFile = trapWriter.TrapFile; trapFile = trapWriter.TrapFile;
if (nocache || !System.IO.File.Exists(trapFile)) if (nocache || !System.IO.File.Exists(trapFile))

View File

@@ -13,33 +13,38 @@ namespace Semmle.Extraction.CIL.Entities
public class File : LabelledEntity, IFile public class File : LabelledEntity, IFile
{ {
protected readonly string path; protected readonly string OriginalPath;
protected readonly PathTransformer.ITransformedPath TransformedPath;
public File(Context cx, string path) : base(cx) public File(Context cx, string path) : base(cx)
{ {
this.path = Semmle.Extraction.Entities.File.PathAsDatabaseString(path); this.OriginalPath = path;
TransformedPath = cx.cx.Extractor.PathTransformer.Transform(OriginalPath);
} }
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
trapFile.Write(Semmle.Extraction.Entities.File.PathAsDatabaseId(path)); trapFile.Write(TransformedPath.DatabaseId);
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return GetType() == obj.GetType() && path == ((File)obj).path; return GetType() == obj.GetType() && OriginalPath == ((File)obj).OriginalPath;
} }
public override int GetHashCode() => 11 * path.GetHashCode(); public override int GetHashCode() => 11 * OriginalPath.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents public override IEnumerable<IExtractionProduct> Contents
{ {
get get
{ {
var parent = cx.CreateFolder(System.IO.Path.GetDirectoryName(path)); if (TransformedPath.ParentDirectory is PathTransformer.ITransformedPath dir)
yield return parent; {
yield return Tuples.containerparent(parent, this); var parent = cx.CreateFolder(dir);
yield return Tuples.files(this, path, System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetExtension(path).Substring(1)); yield return parent;
yield return Tuples.containerparent(parent, this);
}
yield return Tuples.files(this, TransformedPath.Value, TransformedPath.NameWithoutExtension, TransformedPath.Extension);
} }
} }
@@ -65,9 +70,9 @@ namespace Semmle.Extraction.CIL.Entities
var text = file.Contents; var text = file.Contents;
if (text == null) if (text == null)
cx.cx.Extractor.Logger.Log(Util.Logging.Severity.Warning, string.Format("PDB source file {0} could not be found", path)); cx.cx.Extractor.Logger.Log(Util.Logging.Severity.Warning, string.Format("PDB source file {0} could not be found", OriginalPath));
else else
cx.cx.TrapWriter.Archive(path, text); cx.cx.TrapWriter.Archive(TransformedPath, text);
yield return Tuples.file_extraction_mode(this, 2); yield return Tuples.file_extraction_mode(this, 2);
} }

View File

@@ -9,16 +9,16 @@ namespace Semmle.Extraction.CIL.Entities
public sealed class Folder : LabelledEntity, IFolder public sealed class Folder : LabelledEntity, IFolder
{ {
readonly string path; readonly PathTransformer.ITransformedPath TransformedPath;
public Folder(Context cx, string path) : base(cx) public Folder(Context cx, PathTransformer.ITransformedPath path) : base(cx)
{ {
this.path = path; this.TransformedPath = path;
} }
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
trapFile.Write(Semmle.Extraction.Entities.File.PathAsDatabaseId(path)); trapFile.Write(TransformedPath.DatabaseId);
} }
public override string IdSuffix => ";folder"; public override string IdSuffix => ";folder";
@@ -27,25 +27,21 @@ namespace Semmle.Extraction.CIL.Entities
{ {
get get
{ {
// On Posix, we could get a Windows directory of the form "C:" if (TransformedPath.ParentDirectory is PathTransformer.ITransformedPath parent)
bool windowsDriveLetter = path.Length == 2 && char.IsLetter(path[0]) && path[1] == ':';
var parent = Path.GetDirectoryName(path);
if (parent != null && !windowsDriveLetter)
{ {
var parentFolder = cx.CreateFolder(parent); var parentFolder = cx.CreateFolder(parent);
yield return parentFolder; yield return parentFolder;
yield return Tuples.containerparent(parentFolder, this); yield return Tuples.containerparent(parentFolder, this);
} }
yield return Tuples.folders(this, Semmle.Extraction.Entities.File.PathAsDatabaseString(path), Path.GetFileName(path)); yield return Tuples.folders(this, TransformedPath.Value, TransformedPath.NameWithoutExtension);
} }
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is Folder folder && path == folder.path; return obj is Folder folder && TransformedPath == folder.TransformedPath;
} }
public override int GetHashCode() => path.GetHashCode(); public override int GetHashCode() => TransformedPath.GetHashCode();
} }
} }

View File

@@ -201,7 +201,7 @@ namespace Semmle.Extraction.CIL
#region Locations #region Locations
readonly CachedFunction<PDB.ISourceFile, PdbSourceFile> sourceFiles; readonly CachedFunction<PDB.ISourceFile, PdbSourceFile> sourceFiles;
readonly CachedFunction<string, Folder> folders; readonly CachedFunction<PathTransformer.ITransformedPath, Folder> folders;
readonly CachedFunction<PDB.Location, PdbSourceLocation> sourceLocations; readonly CachedFunction<PDB.Location, PdbSourceLocation> sourceLocations;
/// <summary> /// <summary>
@@ -216,7 +216,7 @@ namespace Semmle.Extraction.CIL
/// </summary> /// </summary>
/// <param name="path">The path of the folder.</param> /// <param name="path">The path of the folder.</param>
/// <returns>A folder entity.</returns> /// <returns>A folder entity.</returns>
public Folder CreateFolder(string path) => folders[path]; public Folder CreateFolder(PathTransformer.ITransformedPath path) => folders[path];
/// <summary> /// <summary>
/// Creates a source location. /// Creates a source location.

View File

@@ -25,12 +25,15 @@ namespace Semmle.Extraction.CSharp
public readonly ILogger Logger; public readonly ILogger Logger;
public Analyser(IProgressMonitor pm, ILogger logger) public readonly PathTransformer PathTransformer;
public Analyser(IProgressMonitor pm, ILogger logger, PathTransformer pathTransformer)
{ {
Logger = logger; Logger = logger;
Logger.Log(Severity.Info, "EXTRACTION STARTING at {0}", DateTime.Now); Logger.Log(Severity.Info, "EXTRACTION STARTING at {0}", DateTime.Now);
stopWatch.Start(); stopWatch.Start();
progressMonitor = pm; progressMonitor = pm;
PathTransformer = pathTransformer;
} }
CSharpCompilation compilation; CSharpCompilation compilation;
@@ -64,7 +67,7 @@ namespace Semmle.Extraction.CSharp
layout = new Layout(); layout = new Layout();
this.options = options; this.options = options;
this.compilation = compilation; this.compilation = compilation;
extractor = new Extraction.Extractor(false, GetOutputName(compilation, commandLineArguments), Logger); extractor = new Extraction.Extractor(false, GetOutputName(compilation, commandLineArguments), Logger, PathTransformer);
LogDiagnostics(); LogDiagnostics();
SetReferencePaths(); SetReferencePaths();
@@ -114,7 +117,7 @@ namespace Semmle.Extraction.CSharp
{ {
compilation = compilationIn; compilation = compilationIn;
layout = new Layout(); layout = new Layout();
extractor = new Extraction.Extractor(true, null, Logger); extractor = new Extraction.Extractor(true, null, Logger, PathTransformer);
this.options = options; this.options = options;
LogExtractorInfo(Extraction.Extractor.Version); LogExtractorInfo(Extraction.Extractor.Version);
SetReferencePaths(); SetReferencePaths();
@@ -227,9 +230,10 @@ namespace Semmle.Extraction.CSharp
try try
{ {
var assemblyPath = extractor.OutputPath; var assemblyPath = extractor.OutputPath;
var transformedAssemblyPath = PathTransformer.Transform(assemblyPath);
var assembly = compilation.Assembly; var assembly = compilation.Assembly;
var projectLayout = layout.LookupProjectOrDefault(assemblyPath); var projectLayout = layout.LookupProjectOrDefault(transformedAssemblyPath);
var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true, options.TrapCompression); var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedAssemblyPath, true, options.TrapCompression);
compilationTrapFile = trapWriter; // Dispose later compilationTrapFile = trapWriter; // Dispose later
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true)); var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true));
@@ -257,8 +261,9 @@ namespace Semmle.Extraction.CSharp
stopwatch.Start(); stopwatch.Start();
var assemblyPath = r.FilePath; var assemblyPath = r.FilePath;
var projectLayout = layout.LookupProjectOrDefault(assemblyPath); var transformedAssemblyPath = PathTransformer.Transform(assemblyPath);
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true, options.TrapCompression)) var projectLayout = layout.LookupProjectOrDefault(transformedAssemblyPath);
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedAssemblyPath, true, options.TrapCompression))
{ {
var skipExtraction = options.Cache && File.Exists(trapWriter.TrapFile); var skipExtraction = options.Cache && File.Exists(trapWriter.TrapFile);
@@ -357,16 +362,17 @@ namespace Semmle.Extraction.CSharp
var stopwatch = new Stopwatch(); var stopwatch = new Stopwatch();
stopwatch.Start(); stopwatch.Start();
var sourcePath = tree.FilePath; var sourcePath = tree.FilePath;
var transformedSourcePath = PathTransformer.Transform(sourcePath);
var projectLayout = layout.LookupProjectOrNull(sourcePath); var projectLayout = layout.LookupProjectOrNull(transformedSourcePath);
bool excluded = projectLayout == null; bool excluded = projectLayout == null;
string trapPath = excluded ? "" : projectLayout.GetTrapPath(Logger, sourcePath, options.TrapCompression); string trapPath = excluded ? "" : projectLayout.GetTrapPath(Logger, transformedSourcePath, options.TrapCompression);
bool upToDate = false; bool upToDate = false;
if (!excluded) if (!excluded)
{ {
// compilation.Clone() is used to allow symbols to be garbage collected. // compilation.Clone() is used to allow symbols to be garbage collected.
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, sourcePath, false, options.TrapCompression)) using (var trapWriter = projectLayout.CreateTrapWriter(Logger, transformedSourcePath, false, options.TrapCompression))
{ {
upToDate = options.Fast && FileIsUpToDate(sourcePath, trapWriter.TrapFile); upToDate = options.Fast && FileIsUpToDate(sourcePath, trapWriter.TrapFile);

View File

@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Semmle.Util;
namespace Semmle.Extraction.CSharp.Entities namespace Semmle.Extraction.CSharp.Entities
{ {
@@ -22,32 +23,32 @@ namespace Semmle.Extraction.CSharp.Entities
{ {
Extraction.Entities.Assembly.CreateOutputAssembly(cx); Extraction.Entities.Assembly.CreateOutputAssembly(cx);
trapFile.compilations(this, Extraction.Entities.File.PathAsDatabaseString(cwd)); trapFile.compilations(this, FileUtils.ConvertToUnix(cwd));
// Arguments // Arguments
int index = 0; int index = 0;
foreach(var arg in args) foreach (var arg in args)
{ {
trapFile.compilation_args(this, index++, arg); trapFile.compilation_args(this, index++, arg);
} }
// Files // Files
index = 0; index = 0;
foreach(var file in cx.Compilation.SyntaxTrees.Select(tree => Extraction.Entities.File.Create(cx, tree.FilePath))) foreach (var file in cx.Compilation.SyntaxTrees.Select(tree => Extraction.Entities.File.Create(cx, tree.FilePath)))
{ {
trapFile.compilation_compiling_files(this, index++, file); trapFile.compilation_compiling_files(this, index++, file);
} }
// References // References
index = 0; index = 0;
foreach(var file in cx.Compilation.References.OfType<PortableExecutableReference>().Select(r => Extraction.Entities.File.Create(cx, r.FilePath))) foreach (var file in cx.Compilation.References.OfType<PortableExecutableReference>().Select(r => Extraction.Entities.File.Create(cx, r.FilePath)))
{ {
trapFile.compilation_referencing_files(this, index++, file); trapFile.compilation_referencing_files(this, index++, file);
} }
// Diagnostics // Diagnostics
index = 0; index = 0;
foreach(var diag in cx.Compilation.GetDiagnostics().Select(d => new Diagnostic(cx, d))) foreach (var diag in cx.Compilation.GetDiagnostics().Select(d => new Diagnostic(cx, d)))
{ {
trapFile.diagnostic_for(diag, this, 0, index++); trapFile.diagnostic_for(diag, this, 0, index++);
} }
@@ -57,7 +58,7 @@ namespace Semmle.Extraction.CSharp.Entities
{ {
var trapFile = cx.TrapWriter.Writer; var trapFile = cx.TrapWriter.Writer;
int index = 0; int index = 0;
foreach(float metric in p.Metrics) foreach (float metric in p.Metrics)
{ {
trapFile.compilation_time(this, -1, index++, metric); trapFile.compilation_time(this, -1, index++, metric);
} }

View File

@@ -76,16 +76,16 @@ namespace Semmle.Extraction.CSharp
return ExitCode.Ok; return ExitCode.Ok;
} }
using (var analyser = new Analyser(new LogProgressMonitor(logger), logger)) var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
using (var analyser = new Analyser(new LogProgressMonitor(logger), logger, pathTransformer))
using (var references = new BlockingCollection<MetadataReference>()) using (var references = new BlockingCollection<MetadataReference>())
{ {
try try
{ {
var compilerVersion = new CompilerVersion(commandLineArguments); var compilerVersion = new CompilerVersion(commandLineArguments);
bool preserveSymlinks = Environment.GetEnvironmentVariable("SEMMLE_PRESERVE_SYMLINKS") == "true";
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000, preserveSymlinks ? CanonicalPathCache.Symlinks.Preserve : CanonicalPathCache.Symlinks.Follow);
if (compilerVersion.SkipExtraction) if (compilerVersion.SkipExtraction)
{ {
logger.Log(Severity.Warning, " Unrecognized compiler '{0}' because {1}", compilerVersion.SpecifiedCompiler, compilerVersion.SkipReason); logger.Log(Severity.Warning, " Unrecognized compiler '{0}' because {1}", compilerVersion.SpecifiedCompiler, compilerVersion.SkipReason);
@@ -317,7 +317,10 @@ namespace Semmle.Extraction.CSharp
ILogger logger, ILogger logger,
CommonOptions options) CommonOptions options)
{ {
using (var analyser = new Analyser(pm, logger)) var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
using (var analyser = new Analyser(pm, logger, pathTransformer))
using (var references = new BlockingCollection<MetadataReference>()) using (var references = new BlockingCollection<MetadataReference>())
{ {
try try

View File

@@ -0,0 +1,48 @@
using Xunit;
namespace Semmle.Extraction.Tests
{
public class FilePatternTests
{
[Fact]
public void TestRegexCompilation()
{
var fp = new FilePattern("/hadoop*");
Assert.Equal("^hadoop[^/]*.*", fp.RegexPattern);
fp = new FilePattern("**/org/apache/hadoop");
Assert.Equal("^.*/org/apache/hadoop.*", fp.RegexPattern);
fp = new FilePattern("hadoop-common/**/test// ");
Assert.Equal("^hadoop-common/.*/test(?<doubleslash>/).*", fp.RegexPattern);
fp = new FilePattern(@"-C:\agent\root\asdf//");
Assert.Equal("^C:/agent/root/asdf(?<doubleslash>/).*", fp.RegexPattern);
fp = new FilePattern(@"-C:\agent+\[root]\asdf//");
Assert.Equal(@"^C:/agent\+/\[root]/asdf(?<doubleslash>/).*", fp.RegexPattern);
}
[Fact]
public void TestMatching()
{
var fp1 = new FilePattern(@"C:\agent\root\abc//");
var fp2 = new FilePattern(@"C:\agent\root\def//ghi");
var patterns = new[] { fp1, fp2 };
var success = FilePattern.Matches(patterns, @"C:\agent\root\abc\file.cs", out var s);
Assert.True(success);
Assert.Equal("/file.cs", s);
success = FilePattern.Matches(patterns, @"C:\agent\root\def\ghi\file.cs", out s);
Assert.True(success);
Assert.Equal("/ghi/file.cs", s);
success = FilePattern.Matches(patterns, @"C:\agent\root\def\file.cs", out s);
Assert.False(success);
}
[Fact]
public void TestInvalidPatterns()
{
Assert.Throws<InvalidFilePatternException>(() => new FilePattern("/abc//def//ghi"));
Assert.Throws<InvalidFilePatternException>(() => new FilePattern("/abc**def"));
}
}
}

View File

@@ -5,6 +5,26 @@ using System.Runtime.InteropServices;
namespace Semmle.Extraction.Tests namespace Semmle.Extraction.Tests
{ {
struct TransformedPathStub : PathTransformer.ITransformedPath
{
readonly string value;
public TransformedPathStub(string value) => this.value = value;
public string Value => value;
public string Extension => throw new System.NotImplementedException();
public string NameWithoutExtension => throw new System.NotImplementedException();
public PathTransformer.ITransformedPath ParentDirectory => throw new System.NotImplementedException();
public string DatabaseId => throw new System.NotImplementedException();
public PathTransformer.ITransformedPath WithSuffix(string suffix)
{
throw new System.NotImplementedException();
}
}
public class Layout public class Layout
{ {
readonly ILogger Logger = new LoggerMock(); readonly ILogger Logger = new LoggerMock();
@@ -13,10 +33,10 @@ namespace Semmle.Extraction.Tests
public void TestDefaultLayout() public void TestDefaultLayout()
{ {
var layout = new Semmle.Extraction.Layout(null, null, null); var layout = new Semmle.Extraction.Layout(null, null, null);
var project = layout.LookupProjectOrNull("foo.cs"); var project = layout.LookupProjectOrNull(new TransformedPathStub("foo.cs"));
// All files are mapped when there's no layout file. // All files are mapped when there's no layout file.
Assert.True(layout.FileInLayout("foo.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("foo.cs")));
// Test trap filename // Test trap filename
var tmpDir = Path.GetTempPath(); var tmpDir = Path.GetTempPath();
@@ -28,13 +48,13 @@ namespace Semmle.Extraction.Tests
Assert.NotEqual(Directory.GetCurrentDirectory(), tmpDir); Assert.NotEqual(Directory.GetCurrentDirectory(), tmpDir);
return; return;
} }
var f1 = project.GetTrapPath(Logger, "foo.cs", TrapWriter.CompressionMode.Gzip); var f1 = project.GetTrapPath(Logger, new TransformedPathStub("foo.cs"), TrapWriter.CompressionMode.Gzip);
var g1 = TrapWriter.NestPaths(Logger, tmpDir, "foo.cs.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE); var g1 = TrapWriter.NestPaths(Logger, tmpDir, "foo.cs.trap.gz");
Assert.Equal(f1, g1); Assert.Equal(f1, g1);
// Test trap file generation // Test trap file generation
var trapwriterFilename = project.GetTrapPath(Logger, "foo.cs", TrapWriter.CompressionMode.Gzip); var trapwriterFilename = project.GetTrapPath(Logger, new TransformedPathStub("foo.cs"), TrapWriter.CompressionMode.Gzip);
using (var trapwriter = project.CreateTrapWriter(Logger, "foo.cs", false, TrapWriter.CompressionMode.Gzip)) using (var trapwriter = project.CreateTrapWriter(Logger, new TransformedPathStub("foo.cs"), false, TrapWriter.CompressionMode.Gzip))
{ {
trapwriter.Emit("1=*"); trapwriter.Emit("1=*");
Assert.False(File.Exists(trapwriterFilename)); Assert.False(File.Exists(trapwriterFilename));
@@ -63,23 +83,23 @@ namespace Semmle.Extraction.Tests
var layout = new Semmle.Extraction.Layout(null, null, "layout.txt"); var layout = new Semmle.Extraction.Layout(null, null, "layout.txt");
// Test general pattern matching // Test general pattern matching
Assert.True(layout.FileInLayout("bar.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("bar.cs")));
Assert.False(layout.FileInLayout("foo.cs")); Assert.False(layout.FileInLayout(new TransformedPathStub("foo.cs")));
Assert.False(layout.FileInLayout("goo.cs")); Assert.False(layout.FileInLayout(new TransformedPathStub("goo.cs")));
Assert.False(layout.FileInLayout("excluded/bar.cs")); Assert.False(layout.FileInLayout(new TransformedPathStub("excluded/bar.cs")));
Assert.True(layout.FileInLayout("excluded/foo.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("excluded/foo.cs")));
Assert.True(layout.FileInLayout("included/foo.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("included/foo.cs")));
// Test the trap file // Test the trap file
var project = layout.LookupProjectOrNull("bar.cs"); var project = layout.LookupProjectOrNull(new TransformedPathStub("bar.cs"));
var trapwriterFilename = project.GetTrapPath(Logger, "bar.cs", TrapWriter.CompressionMode.Gzip); var trapwriterFilename = project.GetTrapPath(Logger, new TransformedPathStub("bar.cs"), TrapWriter.CompressionMode.Gzip);
Assert.Equal(TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap"), "bar.cs.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE), Assert.Equal(TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap"), "bar.cs.trap.gz"),
trapwriterFilename); trapwriterFilename);
// Test the source archive // Test the source archive
var trapWriter = project.CreateTrapWriter(Logger, "bar.cs", false, TrapWriter.CompressionMode.Gzip); var trapWriter = project.CreateTrapWriter(Logger, new TransformedPathStub("bar.cs"), false, TrapWriter.CompressionMode.Gzip);
trapWriter.Archive("layout.txt", System.Text.Encoding.ASCII); trapWriter.Archive("layout.txt", new TransformedPathStub("layout.txt"), System.Text.Encoding.ASCII);
var writtenFile = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\archive"), "layout.txt", TrapWriter.InnerPathComputation.ABSOLUTE); var writtenFile = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\archive"), "layout.txt");
Assert.True(File.Exists(writtenFile)); Assert.True(File.Exists(writtenFile));
File.Delete("layout.txt"); File.Delete("layout.txt");
} }
@@ -89,9 +109,9 @@ namespace Semmle.Extraction.Tests
{ {
// When you specify both a trap file and a layout, use the trap file. // When you specify both a trap file and a layout, use the trap file.
var layout = new Semmle.Extraction.Layout(Path.GetFullPath("snapshot\\trap"), null, "something.txt"); var layout = new Semmle.Extraction.Layout(Path.GetFullPath("snapshot\\trap"), null, "something.txt");
Assert.True(layout.FileInLayout("bar.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("bar.cs")));
var f1 = layout.LookupProjectOrNull("foo.cs").GetTrapPath(Logger, "foo.cs", TrapWriter.CompressionMode.Gzip); var f1 = layout.LookupProjectOrNull(new TransformedPathStub("foo.cs")).GetTrapPath(Logger, new TransformedPathStub("foo.cs"), TrapWriter.CompressionMode.Gzip);
var g1 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap"), "foo.cs.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE); var g1 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap"), "foo.cs.trap.gz");
Assert.Equal(f1, g1); Assert.Equal(f1, g1);
} }
@@ -117,26 +137,26 @@ namespace Semmle.Extraction.Tests
var layout = new Semmle.Extraction.Layout(null, null, "layout.txt"); var layout = new Semmle.Extraction.Layout(null, null, "layout.txt");
// Use Section 2 // Use Section 2
Assert.True(layout.FileInLayout("bar.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("bar.cs")));
var f1 = layout.LookupProjectOrNull("bar.cs").GetTrapPath(Logger, "bar.cs", TrapWriter.CompressionMode.Gzip); var f1 = layout.LookupProjectOrNull(new TransformedPathStub("bar.cs")).GetTrapPath(Logger, new TransformedPathStub("bar.cs"), TrapWriter.CompressionMode.Gzip);
var g1 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap2"), "bar.cs.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE); var g1 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap2"), "bar.cs.trap.gz");
Assert.Equal(f1, g1); Assert.Equal(f1, g1);
// Use Section 1 // Use Section 1
Assert.True(layout.FileInLayout("foo.cs")); Assert.True(layout.FileInLayout(new TransformedPathStub("foo.cs")));
var f2 = layout.LookupProjectOrNull("foo.cs").GetTrapPath(Logger, "foo.cs", TrapWriter.CompressionMode.Gzip); var f2 = layout.LookupProjectOrNull(new TransformedPathStub("foo.cs")).GetTrapPath(Logger, new TransformedPathStub("foo.cs"), TrapWriter.CompressionMode.Gzip);
var g2 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap1"), "foo.cs.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE); var g2 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap1"), "foo.cs.trap.gz");
Assert.Equal(f2, g2); Assert.Equal(f2, g2);
// boo.dll is not in the layout, so use layout from first section. // boo.dll is not in the layout, so use layout from first section.
Assert.False(layout.FileInLayout("boo.dll")); Assert.False(layout.FileInLayout(new TransformedPathStub("boo.dll")));
var f3 = layout.LookupProjectOrDefault("boo.dll").GetTrapPath(Logger, "boo.dll", TrapWriter.CompressionMode.Gzip); var f3 = layout.LookupProjectOrDefault(new TransformedPathStub("boo.dll")).GetTrapPath(Logger, new TransformedPathStub("boo.dll"), TrapWriter.CompressionMode.Gzip);
var g3 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap1"), "boo.dll.trap.gz", TrapWriter.InnerPathComputation.ABSOLUTE); var g3 = TrapWriter.NestPaths(Logger, Path.GetFullPath("snapshot\\trap1"), "boo.dll.trap.gz");
Assert.Equal(f3, g3); Assert.Equal(f3, g3);
// boo.cs is not in the layout, so return null // boo.cs is not in the layout, so return null
Assert.False(layout.FileInLayout("boo.cs")); Assert.False(layout.FileInLayout(new TransformedPathStub("boo.cs")));
Assert.Null(layout.LookupProjectOrNull("boo.cs")); Assert.Null(layout.LookupProjectOrNull(new TransformedPathStub("boo.cs")));
} }
[Fact] [Fact]

View File

@@ -0,0 +1,45 @@
using Semmle.Util;
using Xunit;
namespace Semmle.Extraction.Tests
{
class PathCacheStub : IPathCache
{
public string GetCanonicalPath(string path) => path;
}
public class PathTransformerTests
{
[Fact]
public void TestTransformerFile()
{
var spec = new string[]
{
@"#D:\src",
@"C:\agent*\src//",
@"-C:\agent*\src\external",
@"",
@"#empty",
@"",
@"#src2",
@"/agent*//src",
@"",
@"#optsrc",
@"opt/src//"
};
var pathTransformer = new PathTransformer(new PathCacheStub(), spec);
// Windows-style matching
Assert.Equal(@"C:/bar.cs", pathTransformer.Transform(@"C:\bar.cs").Value);
Assert.Equal("D:/src/file.cs", pathTransformer.Transform(@"C:\agent42\src\file.cs").Value);
Assert.Equal("D:/src/file.cs", pathTransformer.Transform(@"C:\agent43\src\file.cs").Value);
Assert.Equal(@"C:/agent43/src/external/file.cs", pathTransformer.Transform(@"C:\agent43\src\external\file.cs").Value);
// Linux-style matching
Assert.Equal(@"src2/src/file.cs", pathTransformer.Transform(@"/agent/src/file.cs").Value);
Assert.Equal(@"src2/src/file.cs", pathTransformer.Transform(@"/agent42/src/file.cs").Value);
Assert.Equal(@"optsrc/file.cs", pathTransformer.Transform(@"/opt/src/file.cs").Value);
}
}
}

View File

@@ -14,7 +14,7 @@ namespace Semmle.Extraction.Tests
string tempDir = System.IO.Path.GetTempPath(); string tempDir = System.IO.Path.GetTempPath();
string root1, root2, root3; string root1, root2, root3;
if(Win32.IsWindows()) if (Win32.IsWindows())
{ {
root1 = "E:"; root1 = "E:";
root2 = "e:"; root2 = "e:";
@@ -27,32 +27,21 @@ namespace Semmle.Extraction.Tests
root3 = "/"; root3 = "/";
} }
string formattedTempDir = tempDir.Replace('/', '\\').Replace(':', '_').Trim('\\');
var logger = new LoggerMock(); var logger = new LoggerMock();
System.IO.Directory.SetCurrentDirectory(tempDir);
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) Assert.Equal($@"C:\Temp\source_archive\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", "def.cs").Replace('/', '\\'));
{
// `Directory.SetCurrentDirectory()` doesn't seem to work on macOS,
// so disable this test on macOS, for now
Assert.NotEqual(Directory.GetCurrentDirectory(), tempDir);
return;
}
Assert.Equal($@"C:\Temp\source_archive\{formattedTempDir}\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", "def.cs", TrapWriter.InnerPathComputation.ABSOLUTE).Replace('/','\\')); Assert.Equal(@"C:\Temp\source_archive\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", "def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", "def.cs", TrapWriter.InnerPathComputation.RELATIVE).Replace('/', '\\')); Assert.Equal(@"C:\Temp\source_archive\E_\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root1}\source\def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\E_\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root1}\source\def.cs", TrapWriter.InnerPathComputation.ABSOLUTE).Replace('/', '\\')); Assert.Equal(@"C:\Temp\source_archive\e_\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root2}\source\def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\e_\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root2}\source\def.cs", TrapWriter.InnerPathComputation.RELATIVE).Replace('/', '\\')); Assert.Equal(@"C:\Temp\source_archive\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}source\def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}source\def.cs", TrapWriter.InnerPathComputation.ABSOLUTE).Replace('/', '\\')); Assert.Equal(@"C:\Temp\source_archive\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}source\def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}source\def.cs", TrapWriter.InnerPathComputation.RELATIVE).Replace('/', '\\')); Assert.Equal(@"C:\Temp\source_archive\diskstation\share\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}{root3}diskstation\share\source\def.cs").Replace('/', '\\'));
Assert.Equal(@"C:\Temp\source_archive\diskstation\share\source\def.cs", TrapWriter.NestPaths(logger, @"C:\Temp\source_archive", $@"{root3}{root3}diskstation\share\source\def.cs", TrapWriter.InnerPathComputation.ABSOLUTE).Replace('/', '\\'));
} }
class LoggerMock : ILogger class LoggerMock : ILogger

View File

@@ -10,93 +10,55 @@ namespace Semmle.Extraction.Entities
File(Context cx, string path) File(Context cx, string path)
: base(cx, path) : base(cx, path)
{ {
Path = path; OriginalPath = path;
TransformedPathLazy = new Lazy<PathTransformer.ITransformedPath>(() => Context.Extractor.PathTransformer.Transform(OriginalPath));
} }
public string Path readonly string OriginalPath;
{ readonly Lazy<PathTransformer.ITransformedPath> TransformedPathLazy;
get; PathTransformer.ITransformedPath TransformedPath => TransformedPathLazy.Value;
private set;
}
public string DatabasePath => PathAsDatabaseId(Path); public override bool NeedsPopulation => Context.DefinesFile(OriginalPath) || OriginalPath == Context.Extractor.OutputPath;
public override bool NeedsPopulation => Context.DefinesFile(Path) || Path == Context.Extractor.OutputPath;
public override void Populate(TextWriter trapFile) public override void Populate(TextWriter trapFile)
{ {
if (Path == null) trapFile.files(this, TransformedPath.Value, TransformedPath.NameWithoutExtension, TransformedPath.Extension);
if (TransformedPath.ParentDirectory is PathTransformer.ITransformedPath dir)
trapFile.containerparent(Folder.Create(Context, dir), this);
var fromSource = TransformedPath.Extension.ToLowerInvariant().Equals("cs");
if (fromSource)
{ {
trapFile.files(this, "", "", ""); foreach (var text in Context.Compilation.SyntaxTrees.
} Where(t => t.FilePath == OriginalPath).
else Select(tree => tree.GetText()))
{
var fi = new FileInfo(Path);
string extension = fi.Extension ?? "";
string name = fi.Name;
name = name.Substring(0, name.Length - extension.Length);
int fromSource = extension.ToLowerInvariant().Equals(".cs") ? 1 : 2;
// remove the dot from the extension
if (extension.Length > 0)
extension = extension.Substring(1);
trapFile.files(this, PathAsDatabaseString(Path), name, extension);
trapFile.containerparent(Folder.Create(Context, fi.Directory), this);
if (fromSource == 1)
{ {
foreach (var text in Context.Compilation.SyntaxTrees.
Where(t => t.FilePath == Path).
Select(tree => tree.GetText()))
{
var rawText = text.ToString(); var rawText = text.ToString();
var lineCounts = LineCounter.ComputeLineCounts(rawText); var lineCounts = LineCounter.ComputeLineCounts(rawText);
if (rawText.Length > 0 && rawText[rawText.Length - 1] != '\n') lineCounts.Total++; if (rawText.Length > 0 && rawText[rawText.Length - 1] != '\n') lineCounts.Total++;
trapFile.numlines(this, lineCounts); trapFile.numlines(this, lineCounts);
Context.TrapWriter.Archive(fi.FullName, text.Encoding); Context.TrapWriter.Archive(OriginalPath, TransformedPath, text.Encoding ?? System.Text.Encoding.Default);
}
} }
trapFile.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0);
} }
trapFile.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0);
} }
public override void WriteId(System.IO.TextWriter trapFile) public override void WriteId(System.IO.TextWriter trapFile)
{ {
if (Path is null) trapFile.Write(TransformedPath.DatabaseId);
trapFile.Write("GENERATED;sourcefile"); trapFile.Write(";sourcefile");
else
{
trapFile.Write(DatabasePath);
trapFile.Write(";sourcefile");
}
} }
/// <summary>
/// Converts a path string into a string to use as an ID
/// in the QL database.
/// </summary>
/// <param name="path">An absolute path.</param>
/// <returns>The database ID.</returns>
public static string PathAsDatabaseId(string path)
{
if (path.Length >= 2 && path[1] == ':' && Char.IsLower(path[0]))
path = Char.ToUpper(path[0]) + "_" + path.Substring(2);
return path.Replace('\\', '/').Replace(":", "_");
}
public static string PathAsDatabaseString(string path) => path.Replace('\\', '/');
public static File Create(Context cx, string path) => FileFactory.Instance.CreateEntity(cx, path); public static File Create(Context cx, string path) => FileFactory.Instance.CreateEntity(cx, path);
public static File CreateGenerated(Context cx) => GeneratedFile.Create(cx); public static File CreateGenerated(Context cx) => GeneratedFile.Create(cx);
class GeneratedFile : File class GeneratedFile : File
{ {
GeneratedFile(Context cx) GeneratedFile(Context cx) : base(cx, "") { }
: base(cx, "") { }
public override bool NeedsPopulation => true; public override bool NeedsPopulation => true;

View File

@@ -2,65 +2,44 @@ using System.IO;
namespace Semmle.Extraction.Entities namespace Semmle.Extraction.Entities
{ {
sealed class Folder : CachedEntity<DirectoryInfo> sealed class Folder : CachedEntity<PathTransformer.ITransformedPath>
{ {
Folder(Context cx, DirectoryInfo init) Folder(Context cx, PathTransformer.ITransformedPath init) : base(cx, init) { }
: base(cx, init)
{
Path = init.FullName;
}
public string Path
{
get;
private set;
}
public string DatabasePath => File.PathAsDatabaseId(Path);
public override void Populate(TextWriter trapFile) public override void Populate(TextWriter trapFile)
{ {
// Ensure that the name of the root directory is consistent trapFile.folders(this, symbol.Value, symbol.NameWithoutExtension);
// with the XmlTrapWriter. if (symbol.ParentDirectory is PathTransformer.ITransformedPath parent)
// Linux/Windows: java.io.File.getName() returns "" trapFile.containerparent(Create(Context, parent), this);
// On Linux: System.IO.DirectoryInfo.Name returns "/"
// On Windows: System.IO.DirectoryInfo.Name returns "L:\"
string shortName = symbol.Parent == null ? "" : symbol.Name;
trapFile.folders(this, File.PathAsDatabaseString(Path), shortName);
if (symbol.Parent != null)
{
trapFile.containerparent(Create(Context, symbol.Parent), this);
}
} }
public override bool NeedsPopulation => true; public override bool NeedsPopulation => true;
public override void WriteId(System.IO.TextWriter trapFile) public override void WriteId(System.IO.TextWriter trapFile)
{ {
trapFile.Write(DatabasePath); trapFile.Write(symbol.DatabaseId);
trapFile.Write(";folder"); trapFile.Write(";folder");
} }
public static Folder Create(Context cx, DirectoryInfo folder) => public static Folder Create(Context cx, PathTransformer.ITransformedPath folder) =>
FolderFactory.Instance.CreateEntity2(cx, folder); FolderFactory.Instance.CreateEntity2(cx, folder);
public override Microsoft.CodeAnalysis.Location ReportingLocation => null; public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
class FolderFactory : ICachedEntityFactory<DirectoryInfo, Folder> class FolderFactory : ICachedEntityFactory<PathTransformer.ITransformedPath, Folder>
{ {
public static readonly FolderFactory Instance = new FolderFactory(); public static readonly FolderFactory Instance = new FolderFactory();
public Folder Create(Context cx, DirectoryInfo init) => new Folder(cx, init); public Folder Create(Context cx, PathTransformer.ITransformedPath init) => new Folder(cx, init);
} }
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public override int GetHashCode() => Path.GetHashCode(); public override int GetHashCode() => symbol.GetHashCode();
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is Folder folder && folder.Path == Path; return obj is Folder folder && Equals(folder.symbol, symbol);
} }
} }
} }

View File

@@ -81,6 +81,11 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
ILogger Logger { get; } ILogger Logger { get; }
/// <summary>
/// The path transformer to apply.
/// </summary>
PathTransformer PathTransformer { get; }
/// <summary> /// <summary>
/// Creates a new context. /// Creates a new context.
/// </summary> /// </summary>
@@ -111,11 +116,14 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="standalone">If the extraction is standalone.</param> /// <param name="standalone">If the extraction is standalone.</param>
/// <param name="outputPath">The name of the output DLL/EXE, or null if not specified (standalone extraction).</param> /// <param name="outputPath">The name of the output DLL/EXE, or null if not specified (standalone extraction).</param>
public Extractor(bool standalone, string outputPath, ILogger logger) /// <param name="logger">The object used for logging.</param>
/// <param name="pathTransformer">The object used for path transformations.</param>
public Extractor(bool standalone, string outputPath, ILogger logger, PathTransformer pathTransformer)
{ {
Standalone = standalone; Standalone = standalone;
OutputPath = outputPath; OutputPath = outputPath;
Logger = logger; Logger = logger;
PathTransformer = pathTransformer;
} }
// Limit the number of error messages in the log file // Limit the number of error messages in the log file
@@ -205,5 +213,7 @@ namespace Semmle.Extraction
public ILogger Logger { get; private set; } public ILogger Logger { get; private set; }
public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})"; public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})";
public PathTransformer PathTransformer { get; }
} }
} }

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Semmle.Util;
namespace Semmle.Extraction
{
public sealed class InvalidFilePatternException : Exception
{
public InvalidFilePatternException(string pattern, string message) :
base($"Invalid file pattern '{pattern}': {message}")
{ }
}
/// <summary>
/// A file pattern, as used in either an extractor layout file or
/// a path transformer file.
/// </summary>
public sealed class FilePattern
{
/// <summary>
/// Whether this is an inclusion pattern.
/// </summary>
public bool Include { get; }
public FilePattern(string pattern)
{
Include = true;
if (pattern.StartsWith("-"))
{
pattern = pattern.Substring(1);
Include = false;
}
pattern = FileUtils.ConvertToUnix(pattern.Trim()).TrimStart('/');
RegexPattern = BuildRegex(pattern).ToString();
}
/// <summary>
/// Constructs a regex string from a file pattern. Throws
/// `InvalidFilePatternException` for invalid patterns.
/// </summary>
static StringBuilder BuildRegex(string pattern)
{
bool HasCharAt(int i, Predicate<char> p) =>
i >= 0 && i < pattern.Length && p(pattern[i]);
var sb = new StringBuilder();
var i = 0;
var seenDoubleSlash = false;
sb.Append('^');
while (i < pattern.Length)
{
if (pattern[i] == '/')
{
if (HasCharAt(i + 1, c => c == '/'))
{
if (seenDoubleSlash)
throw new InvalidFilePatternException(pattern, "'//' is allowed at most once.");
sb.Append("(?<doubleslash>/)");
i += 2;
seenDoubleSlash = true;
}
else
{
sb.Append('/');
i++;
}
}
else if (pattern[i] == '*')
{
if (HasCharAt(i + 1, c => c == '*'))
{
if (HasCharAt(i - 1, c => c != '/'))
throw new InvalidFilePatternException(pattern, "'**' preceeded by non-`/` character.");
if (HasCharAt(i + 2, c => c != '/'))
throw new InvalidFilePatternException(pattern, "'**' succeeded by non-`/` character");
sb.Append(".*");
i += 2;
}
else
{
sb.Append("[^/]*");
i++;
}
}
else
sb.Append(Regex.Escape(pattern[i++].ToString()));
}
return sb.Append(".*");
}
/// <summary>
/// The regex pattern compiled from this file pattern.
/// </summary>
public string RegexPattern { get; }
/// <summary>
/// Returns `true` if the set of file patterns `patterns` match the path `path`.
/// If so, `transformerSuffix` will contain the part of `path` that needs to be
/// suffixed when using path transformers.
/// </summary>
public static bool Matches(IEnumerable<FilePattern> patterns, string path, out string transformerSuffix)
{
path = FileUtils.ConvertToUnix(path).TrimStart('/');
foreach (var pattern in patterns.Reverse())
{
var m = new Regex(pattern.RegexPattern).Match(path);
if (m.Success)
{
if (pattern.Include)
{
transformerSuffix = m.Groups.TryGetValue("doubleslash", out var group)
? path.Substring(group.Index)
: path;
return true;
}
transformerSuffix = null;
return false;
}
}
transformerSuffix = null;
return false;
}
}
}

View File

@@ -54,14 +54,15 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="srcFile">The source file.</param> /// <param name="srcFile">The source file.</param>
/// <returns>The full filepath of the trap file.</returns> /// <returns>The full filepath of the trap file.</returns>
public string GetTrapPath(ILogger logger, string srcFile, TrapWriter.CompressionMode trapCompression) => TrapWriter.TrapPath(logger, TRAP_FOLDER, srcFile, trapCompression); public string GetTrapPath(ILogger logger, PathTransformer.ITransformedPath srcFile, TrapWriter.CompressionMode trapCompression) =>
TrapWriter.TrapPath(logger, TRAP_FOLDER, srcFile, trapCompression);
/// <summary> /// <summary>
/// Creates a trap writer for a given source/assembly file. /// Creates a trap writer for a given source/assembly file.
/// </summary> /// </summary>
/// <param name="srcFile">The source file.</param> /// <param name="srcFile">The source file.</param>
/// <returns>A newly created TrapWriter.</returns> /// <returns>A newly created TrapWriter.</returns>
public TrapWriter CreateTrapWriter(ILogger logger, string srcFile, bool discardDuplicates, TrapWriter.CompressionMode trapCompression) => public TrapWriter CreateTrapWriter(ILogger logger, PathTransformer.ITransformedPath srcFile, bool discardDuplicates, TrapWriter.CompressionMode trapCompression) =>
new TrapWriter(logger, srcFile, TRAP_FOLDER, SOURCE_ARCHIVE, discardDuplicates, trapCompression); new TrapWriter(logger, srcFile, TRAP_FOLDER, SOURCE_ARCHIVE, discardDuplicates, trapCompression);
} }
@@ -73,7 +74,7 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="sourceFile">The file to look up.</param> /// <param name="sourceFile">The file to look up.</param>
/// <returns>The relevant subproject, or null if not found.</returns> /// <returns>The relevant subproject, or null if not found.</returns>
public SubProject LookupProjectOrNull(string sourceFile) public SubProject LookupProjectOrNull(PathTransformer.ITransformedPath sourceFile)
{ {
if (!useLayoutFile) return DefaultProject; if (!useLayoutFile) return DefaultProject;
@@ -89,7 +90,7 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="sourceFile">The file to look up.</param> /// <param name="sourceFile">The file to look up.</param>
/// <returns>The relevant subproject, or DefaultProject if not found.</returns> /// <returns>The relevant subproject, or DefaultProject if not found.</returns>
public SubProject LookupProjectOrDefault(string sourceFile) public SubProject LookupProjectOrDefault(PathTransformer.ITransformedPath sourceFile)
{ {
return LookupProjectOrNull(sourceFile) ?? DefaultProject; return LookupProjectOrNull(sourceFile) ?? DefaultProject;
} }
@@ -133,7 +134,7 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="path">The absolute path of the file to query.</param> /// <param name="path">The absolute path of the file to query.</param>
/// <returns>True iff there is no layout file or the layout file specifies the file.</returns> /// <returns>True iff there is no layout file or the layout file specifies the file.</returns>
public bool FileInLayout(string path) => LookupProjectOrNull(path) != null; public bool FileInLayout(PathTransformer.ITransformedPath path) => LookupProjectOrNull(path) != null;
void ReadLayoutFile(string layout) void ReadLayoutFile(string layout)
{ {
@@ -169,33 +170,7 @@ namespace Semmle.Extraction
sealed class LayoutBlock sealed class LayoutBlock
{ {
struct Condition private readonly List<FilePattern> filePatterns = new List<FilePattern>();
{
private readonly bool include;
private readonly string prefix;
public bool Include => include;
public string Prefix => prefix;
public Condition(string line)
{
include = false;
if (line.StartsWith("-"))
line = line.Substring(1);
else
include = true;
prefix = Normalise(line.Trim());
}
static public string Normalise(string path)
{
path = Path.GetFullPath(path);
return path.Replace('\\', '/');
}
}
private readonly List<Condition> conditions = new List<Condition>();
public Layout.SubProject Directories; public Layout.SubProject Directories;
@@ -221,23 +196,11 @@ namespace Semmle.Extraction
ReadVariable("ODASA_BUILD_ERROR_DIR", lines[i++]); ReadVariable("ODASA_BUILD_ERROR_DIR", lines[i++]);
while (i < lines.Length && !lines[i].StartsWith("#")) while (i < lines.Length && !lines[i].StartsWith("#"))
{ {
conditions.Add(new Condition(lines[i++])); filePatterns.Add(new FilePattern(lines[i++]));
} }
return i; return i;
} }
public bool Matches(string path) public bool Matches(PathTransformer.ITransformedPath path) => FilePattern.Matches(filePatterns, path.Value, out var _);
{
bool matches = false;
path = Condition.Normalise(path);
foreach (Condition condition in conditions)
{
if (condition.Include)
matches |= path.StartsWith(condition.Prefix);
else
matches &= !path.StartsWith(condition.Prefix);
}
return matches;
}
} }
} }

View File

@@ -0,0 +1,191 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics.CodeAnalysis;
using Semmle.Util;
namespace Semmle.Extraction
{
/// <summary>
/// A class for interpreting path transformers specified using the environment
/// variable `CODEQL_PATH_TRANSFORMER`.
/// </summary>
public sealed class PathTransformer
{
public class InvalidPathTransformerException : Exception
{
public InvalidPathTransformerException(string message) :
base($"Invalid path transformer specification: {message}")
{ }
}
/// <summary>
/// A transformed path.
/// </summary>
public interface ITransformedPath
{
string Value { get; }
string Extension { get; }
string NameWithoutExtension { get; }
ITransformedPath ParentDirectory { get; }
ITransformedPath WithSuffix(string suffix);
string DatabaseId { get; }
}
struct TransformedPath : ITransformedPath
{
public TransformedPath(string value) { this.value = value; }
readonly string value;
public string Value => value;
public string Extension
{
get
{
var extension = Path.GetExtension(value);
if (string.IsNullOrEmpty(extension))
{
return "";
}
else
{
return extension.Substring(1);
}
}
}
public string NameWithoutExtension => Path.GetFileNameWithoutExtension(value);
public ITransformedPath ParentDirectory
{
get
{
var dir = Path.GetDirectoryName(value);
if (dir is null)
return null;
var isWindowsDriveLetter = dir.Length == 2 && char.IsLetter(dir[0]) && dir[1] == ':';
if (isWindowsDriveLetter)
return null;
return new TransformedPath(FileUtils.ConvertToUnix(dir));
}
}
public ITransformedPath WithSuffix(string suffix) => new TransformedPath(value + suffix);
public string DatabaseId
{
get
{
var ret = value;
if (ret.Length >= 2 && ret[1] == ':' && Char.IsLower(ret[0]))
ret = Char.ToUpper(ret[0]) + "_" + ret.Substring(2);
return ret.Replace('\\', '/').Replace(":", "_");
}
}
public override int GetHashCode() => 11 * value.GetHashCode();
public override bool Equals(object obj) => obj is TransformedPath tp && tp.value == value;
public override string ToString() => value;
}
readonly Func<string, string> transform;
/// <summary>
/// Returns the path obtained by transforming `path`.
/// </summary>
public ITransformedPath Transform(string path) => new TransformedPath(transform(path));
/// <summary>
/// Default constructor reads parameters from the environment.
/// </summary>
public PathTransformer(IPathCache pathCache) :
this(pathCache, Environment.GetEnvironmentVariable("CODEQL_PATH_TRANSFORMER") is string file ? File.ReadAllLines(file) : null)
{
}
/// <summary>
/// Creates a path transformer based on the specification in `lines`.
/// Throws `InvalidPathTransformerException` for invalid specifications.
/// </summary>
public PathTransformer(IPathCache pathCache, string[] lines)
{
if (lines is null)
{
transform = path => FileUtils.ConvertToUnix(pathCache.GetCanonicalPath(path));
return;
}
var sections = ParsePathTransformerSpec(lines);
transform = path =>
{
path = FileUtils.ConvertToUnix(pathCache.GetCanonicalPath(path));
foreach (var section in sections)
{
if (section.Matches(path, out var transformed))
return transformed;
}
return path;
};
}
static IEnumerable<TransformerSection> ParsePathTransformerSpec(string[] lines)
{
var sections = new List<TransformerSection>();
try
{
int i = 0;
while (i < lines.Length && !lines[i].StartsWith("#"))
i++;
while (i < lines.Length)
{
var section = new TransformerSection(lines, ref i);
sections.Add(section);
}
if (sections.Count == 0)
throw new InvalidPathTransformerException("contains no sections.");
}
catch (InvalidFilePatternException ex)
{
throw new InvalidPathTransformerException(ex.Message);
}
return sections;
}
}
sealed class TransformerSection
{
readonly string name;
readonly List<FilePattern> filePatterns = new List<FilePattern>();
public TransformerSection(string[] lines, ref int i)
{
name = lines[i++].Substring(1); // skip the '#'
for (; i < lines.Length && !lines[i].StartsWith("#"); i++)
{
var line = lines[i];
if (!string.IsNullOrWhiteSpace(line))
filePatterns.Add(new FilePattern(line));
}
}
public bool Matches(string path, [NotNullWhen(true)] out string transformed)
{
if (FilePattern.Matches(filePatterns, path, out var suffix))
{
transformed = FileUtils.ConvertToUnix(name) + suffix;
return true;
}
transformed = null;
return false;
}
}
}

View File

@@ -14,12 +14,6 @@ namespace Semmle.Extraction
public sealed class TrapWriter : IDisposable public sealed class TrapWriter : IDisposable
{ {
public enum InnerPathComputation
{
ABSOLUTE,
RELATIVE
}
public enum CompressionMode public enum CompressionMode
{ {
None, None,
@@ -45,7 +39,7 @@ namespace Semmle.Extraction
readonly CompressionMode TrapCompression; readonly CompressionMode TrapCompression;
public TrapWriter(ILogger logger, string outputfile, string trap, string archive, bool discardDuplicates, CompressionMode trapCompression) public TrapWriter(ILogger logger, PathTransformer.ITransformedPath outputfile, string trap, string archive, bool discardDuplicates, CompressionMode trapCompression)
{ {
Logger = logger; Logger = logger;
TrapCompression = trapCompression; TrapCompression = trapCompression;
@@ -107,16 +101,17 @@ namespace Semmle.Extraction
/// Adds the specified input file to the source archive. It may end up in either the normal or long path area /// Adds the specified input file to the source archive. It may end up in either the normal or long path area
/// of the source archive, depending on the length of its full path. /// of the source archive, depending on the length of its full path.
/// </summary> /// </summary>
/// <param name="inputPath">The path to the input file.</param> /// <param name="originalPath">The path to the input file.</param>
/// <param name="transformedPath">The transformed path to the input file.</param>
/// <param name="inputEncoding">The encoding used by the input file.</param> /// <param name="inputEncoding">The encoding used by the input file.</param>
public void Archive(string inputPath, Encoding inputEncoding) public void Archive(string originalPath, PathTransformer.ITransformedPath transformedPath, Encoding inputEncoding)
{ {
if (string.IsNullOrEmpty(archive)) return; if (string.IsNullOrEmpty(archive)) return;
// Calling GetFullPath makes this use the canonical capitalisation, if the file exists. // Calling GetFullPath makes this use the canonical capitalisation, if the file exists.
string fullInputPath = Path.GetFullPath(inputPath); string fullInputPath = Path.GetFullPath(originalPath);
ArchivePath(fullInputPath, inputEncoding); ArchivePath(fullInputPath, transformedPath, inputEncoding);
} }
/// <summary> /// <summary>
@@ -124,14 +119,11 @@ namespace Semmle.Extraction
/// </summary> /// </summary>
/// <param name="inputPath">The path of the file.</param> /// <param name="inputPath">The path of the file.</param>
/// <param name="contents">The contents of the file.</param> /// <param name="contents">The contents of the file.</param>
public void Archive(string inputPath, string contents) public void Archive(PathTransformer.ITransformedPath inputPath, string contents)
{ {
if (string.IsNullOrEmpty(archive)) return; if (string.IsNullOrEmpty(archive)) return;
// Calling GetFullPath makes this use the canonical capitalisation, if the file exists. ArchiveContents(inputPath, contents);
string fullInputPath = Path.GetFullPath(inputPath);
ArchiveContents(fullInputPath, contents);
} }
/// <summary> /// <summary>
@@ -210,18 +202,19 @@ namespace Semmle.Extraction
/// source archive less than the system path limit of 260 characters. /// source archive less than the system path limit of 260 characters.
/// </summary> /// </summary>
/// <param name="fullInputPath">The full path to the input file.</param> /// <param name="fullInputPath">The full path to the input file.</param>
/// <param name="transformedPath">The transformed path to the input file.</param>
/// <param name="inputEncoding">The encoding used by the input file.</param> /// <param name="inputEncoding">The encoding used by the input file.</param>
/// <exception cref="PathTooLongException">If the output path in the source archive would /// <exception cref="PathTooLongException">If the output path in the source archive would
/// exceed the system path limit of 260 characters.</exception> /// exceed the system path limit of 260 characters.</exception>
private void ArchivePath(string fullInputPath, Encoding inputEncoding) private void ArchivePath(string fullInputPath, PathTransformer.ITransformedPath transformedPath, Encoding inputEncoding)
{ {
string contents = File.ReadAllText(fullInputPath, inputEncoding); string contents = File.ReadAllText(fullInputPath, inputEncoding);
ArchiveContents(fullInputPath, contents); ArchiveContents(transformedPath, contents);
} }
private void ArchiveContents(string fullInputPath, string contents) private void ArchiveContents(PathTransformer.ITransformedPath transformedPath, string contents)
{ {
string dest = NestPaths(Logger, archive, fullInputPath, InnerPathComputation.ABSOLUTE); string dest = NestPaths(Logger, archive, transformedPath.Value);
string tmpSrcFile = Path.GetTempFileName(); string tmpSrcFile = Path.GetTempFileName();
File.WriteAllText(tmpSrcFile, contents, UTF8); File.WriteAllText(tmpSrcFile, contents, UTF8);
try try
@@ -236,14 +229,11 @@ namespace Semmle.Extraction
} }
} }
public static string NestPaths(ILogger logger, string outerpath, string innerpath, InnerPathComputation innerPathComputation) public static string NestPaths(ILogger logger, string outerpath, string innerpath)
{ {
string nested = innerpath; string nested = innerpath;
if (!string.IsNullOrEmpty(outerpath)) if (!string.IsNullOrEmpty(outerpath))
{ {
if (!Path.IsPathRooted(innerpath) && innerPathComputation == InnerPathComputation.ABSOLUTE)
innerpath = Path.GetFullPath(innerpath);
// Remove all leading path separators / or \ // Remove all leading path separators / or \
// For example, UNC paths have two leading \\ // For example, UNC paths have two leading \\
innerpath = innerpath.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); innerpath = innerpath.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
@@ -276,13 +266,13 @@ namespace Semmle.Extraction
} }
} }
public static string TrapPath(ILogger logger, string folder, string filename, TrapWriter.CompressionMode trapCompression) public static string TrapPath(ILogger logger, string folder, PathTransformer.ITransformedPath path, TrapWriter.CompressionMode trapCompression)
{ {
filename = $"{Path.GetFullPath(filename)}.trap{TrapExtension(trapCompression)}"; var filename = $"{path.Value}.trap{TrapExtension(trapCompression)}";
if (string.IsNullOrEmpty(folder)) if (string.IsNullOrEmpty(folder))
folder = Directory.GetCurrentDirectory(); folder = Directory.GetCurrentDirectory();
return NestPaths(logger, folder, filename, InnerPathComputation.ABSOLUTE); ; return NestPaths(logger, folder, filename);
} }
} }
} }

View File

@@ -222,6 +222,29 @@ namespace Semmle.Util
this.pathStrategy = pathStrategy; this.pathStrategy = pathStrategy;
} }
/// <summary>
/// Create a CanonicalPathCache.
/// </summary>
///
/// <remarks>
/// Creates the appropriate PathStrategy object which encapsulates
/// the correct algorithm. Falls back to different implementations
/// depending on platform.
/// </remarks>
///
/// <param name="maxCapacity">Size of the cache.</param>
/// <param name="symlinks">Policy for following symlinks.</param>
/// <returns>A new CanonicalPathCache.</returns>
public static CanonicalPathCache Create(ILogger logger, int maxCapacity)
{
var preserveSymlinks =
Environment.GetEnvironmentVariable("CODEQL_PRESERVE_SYMLINKS") == "true" ||
Environment.GetEnvironmentVariable("SEMMLE_PRESERVE_SYMLINKS") == "true";
return Create(logger, maxCapacity, preserveSymlinks ? CanonicalPathCache.Symlinks.Preserve : CanonicalPathCache.Symlinks.Follow);
}
/// <summary> /// <summary>
/// Create a CanonicalPathCache. /// Create a CanonicalPathCache.
/// </summary> /// </summary>

View File

@@ -0,0 +1,483 @@
Abstract syntax tree classes for working with Go programs
=========================================================
CodeQL has a large selection of classes for representing the abstract syntax tree of Go programs.
.. include:: ../../reusables/abstract-syntax-tree.rst
Statement classes
-----------------
This table lists all subclasses of `Stmt <https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__.
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Statement syntax | CodeQL class | Superclasses | Remarks |
+===================================================================================================================+===================================================================================================================+===============================================================================================================+===================================================================================================================+
| ``;`` | EmptyStmt_ | | |
| | | | |
| | .. _EmptyStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$EmptyStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ | ExprStmt_ | | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ExprStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExprStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``{`` Stmt_ ``...`` ``}`` | BlockStmt_ | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``if`` Expr_ BlockStmt_ | IfStmt_ | | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _IfStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IfStmt.html | | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``if`` Expr_ BlockStmt_ ``else`` Stmt_ | | | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``if`` Stmt_\ ``;`` Expr_ BlockStmt_ | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``for`` Expr_ BlockStmt_ | ForStmt_ | LoopStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ForStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ForStmt.html | .. _LoopStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LoopStmt.html | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``for`` Stmt_\ ``;`` Expr_\ ``;`` Stmt_ BlockStmt_ | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``for`` Expr_ ``...`` ``=`` ``range`` Expr_ BlockStmt_ | RangeStmt_ | LoopStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RangeStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RangeStmt.html | .. _LoopStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LoopStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _BlockStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BlockStmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``switch`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | ExpressionSwitchStmt_ | SwitchStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ExpressionSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExpressionSwitchStmt.html | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html | |
| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``switch`` Stmt_\ ``;`` Expr_ ``{`` CaseClause_ ``...`` ``}`` | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``switch`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | TypeSwitchStmt_ | SwitchStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _TypeSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$TypeSwitchStmt.html | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html | |
| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``switch`` SimpleAssignStmt_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | |
| | | | |
| .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | | | |
| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``switch`` Stmt_\ ``;`` Expr_\ ``.(type)`` ``{`` CaseClause_ ``...`` ``}`` | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
| .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``select`` ``{`` CommClause_ ``...`` ``}`` | SelectStmt_ | | |
| | | | |
| .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html | .. _SelectStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SelectStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``return`` | ReturnStmt_ | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``return`` Expr_ ``...`` | .. _ReturnStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ReturnStmt.html | | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``break`` | BreakStmt_ | BranchStmt_ | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``break`` LabelName_ | .. _BreakStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BreakStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | |
| | | | |
| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``continue`` | ContinueStmt_ | BranchStmt_ | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``continue`` LabelName_ | .. _ContinueStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ContinueStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | |
| | | | |
| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``goto`` LabelName_ | GotoStmt_ | BranchStmt_ | |
| | | | |
| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | .. _GotoStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$GotoStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``fallthrough`` | FallthroughStmt_ | BranchStmt_ | can only occur as final non-empty child of a CaseClause_ in an ExpressionSwitchStmt_ |
| | | | |
| | .. _FallthroughStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$FallthroughStmt.html | .. _BranchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BranchStmt.html | .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html |
| | | | .. _ExpressionSwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ExpressionSwitchStmt.html |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| LabelName_\ ``:`` Stmt_ | LabeledStmt_ | | |
| | | | |
| .. _LabelName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html | .. _LabeledStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$LabeledStmt.html | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``var`` VariableName_ TypeName_ | DeclStmt_ | | |
| | | | |
| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | .. _DeclStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DeclStmt.html | | |
| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``const`` VariableName_ ``=`` Expr_ | | | |
| | | | |
| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``type`` TypeName_ TypeExpr_ | | | |
| | | | |
| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | |
| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``type`` TypeName_ ``=`` TypeExpr_ | | | |
| | | | |
| .. _TypeName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html | | | |
| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``...`` ``=`` Expr_ ``...`` | AssignStmt_ | SimpleAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AssignStmt.html | .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| VariableName_ ``...`` ``:=`` Expr_ ``...`` | DefineStmt_ | SimpleAssignStmt_, Assignment_ | |
| | | | |
| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | .. _DefineStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DefineStmt.html | .. _SimpleAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SimpleAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``+=`` Expr_ | AddAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AddAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AddAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``-=`` Expr_ | SubAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _SubAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SubAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _MulAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$MulAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``/=`` Expr_ | QuoAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _QuoAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$QuoAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``%=`` Expr_ | RemAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RemAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RemAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``*=`` Expr_ | MulAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _MulAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$MulAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``&=`` Expr_ | AndAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AndAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AndAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``|=`` Expr_ | OrAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _OrAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$OrAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``^=`` Expr_ | XorAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _XorAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$XorAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``<<=`` Expr_ | ShlAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ShlAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ShlAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``>>=`` Expr_ | ShrAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _ShrAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$ShrAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``&^=`` Expr_ | AndNotAssignStmt_ | CompoundAssignStmt_, Assignment_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _AndNotAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$AndNotAssignStmt.html | .. _CompoundAssignStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CompoundAssignStmt.html | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | .. _Assignment: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Assignment.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``++`` | IncStmt_ | IncDecStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _IncStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncStmt.html | .. _IncDecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncDecStmt.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``--`` | DecStmt_ | IncDecStmt_ | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _DecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DecStmt.html | .. _IncDecStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$IncDecStmt.html | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``go`` CallExpr_ | GoStmt_ | | |
| | | | |
| .. _CallExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html | .. _GoStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$GoStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``defer`` CallExpr_ | DeferStmt_ | | |
| | | | |
| .. _CallExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html | .. _DeferStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$DeferStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``<-`` Expr_ | SendStmt_ | | |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _SendStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SendStmt.html | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``case`` Expr_ ``...``\ ``:`` Stmt_ ``...`` | CaseClause_ | | can only occur as child of a SwitchStmt_ |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _CaseClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CaseClause.html | | .. _SwitchStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SwitchStmt.html |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``case`` TypeExpr_ ``...``\ ``:`` Stmt_ ``...`` | | | |
| | | | |
| .. _TypeExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``default:`` Stmt_ ``...`` | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| ``case`` SendStmt_\ ``:`` Stmt_ ``...`` | CommClause_ | | can only occur as child of a SelectStmt_ |
| | | | |
| .. _SendStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SendStmt.html | .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html | | .. _SelectStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$SelectStmt.html |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``case`` RecvStmt_\ ``:`` Stmt_ ``...`` | | | |
| | | | |
| .. _RecvStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RecvStmt.html | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| ``default:`` Stmt_ ``...`` | | | |
| | | | |
| .. _Stmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| Expr_ ``...`` ``=`` RecvExpr_ | RecvStmt_ | | can only occur as child of a CommClause_ |
| | | | |
| .. _Expr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html | .. _RecvStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$RecvStmt.html | | .. _CommClause: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$CommClause.html |
| .. _RecvExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+ | | |
| VariableName_ ``...`` ``:=`` RecvExpr_ | | | |
| | | | |
| .. _VariableName: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html | | | |
| .. _RecvExpr: https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html | | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
| (anything unparseable) | BadStmt_ | | |
| | | | |
| | .. _BadStmt: https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$BadStmt.html | | |
+-------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+
Expression classes
------------------
There are many expression classes, so we present them by category.
All classes in this section are subclasses of
`Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__.
Literals
~~~~~~~~
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| Expression syntax example | CodeQL class | Superclass |
+=========================================+==============================================================================================+====================================================================================================+
| ``23`` | `IntLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$IntLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``4.2`` | `FloatLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FloatLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``4.2 + 2.7i`` | `ImagLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ImagLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``'a'`` | `CharLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CharLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``"Hello"`` | `StringLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StringLit.html>`__ | `BasicLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BasicLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``func(x, y int) int { return x + y }`` | `FuncLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FuncLit.html>`__ | `FuncDef <https://help.semmle.com/qldoc/go/semmle/go/Decls.qll/type.Decls$FuncDef.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``map[string]int{"A": 1, "B": 2}`` | `MapLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MapLit.html>`__ | `CompositeLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CompositeLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``Point3D{0.5, -0.5, 0.5}`` | `StructLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StructLit.html>`__ | `CompositeLit <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CompositeLit.html>`__ |
+-----------------------------------------+----------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
Unary expressions
~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of
`UnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$UnaryExpr.html>`__.
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses |
+============================================================================================+========================================================================================================+==================================================================================================================+
| ``+``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `PlusExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$PlusExpr.html>`__ | `ArithmeticUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticUnaryExpr.html>`__ |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| ``-``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `MinusExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MinusExpr.html>`__ | `ArithmeticUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticUnaryExpr.html>`__ |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| ``!``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `NotExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$NotExpr.html>`__ | `LogicalUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalUnaryExpr.html>`__ |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| ``^``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ComplementExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ComplementExpr.html>`__ | `BitwiseUnaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseUnaryExpr.html>`__ |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| ``&``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AddressExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AddressExpr.html>`__ | |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
| ``<-``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `RecvExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvExpr.html>`__ | |
+--------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+
Binary expressions
~~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of
`BinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BinaryExpr.html>`__.
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses |
+==============================================================================================================================================================================+================================================================================================+============================================================================================================================+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``*`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `MulExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MulExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``/`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `QuoExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$QuoExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``%`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `RemExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RemExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``+`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AddExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AddExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``-`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `SubExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SubExpr.html>`__ | `ArithmeticBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArithmeticBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<<`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ShlExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShlExpr.html>`__ | `ShiftExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShiftExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>>`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `ShrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShrExpr.html>`__ | `ShiftExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ShiftExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&&`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LandExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LandExpr.html>`__ | `LogicalBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``||`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LorExpr.html>`__ | `LogicalBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LogicalBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LssExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LssExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `GtrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$GtrExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``<=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `LeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LeqExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``>=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `GeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$GeqExpr.html>`__ | `RelationalComparisonExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RelationalComparisonExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``==`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `EqlExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqlExpr.html>`__ | `EqualityTestExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqualityTestExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``!=`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `NeqExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$NeqExpr.html>`__ | `EqualityTestExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$EqualityTestExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AndExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AndExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``|`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `OrExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$OrExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``^`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `XorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$XorExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ ``&^`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `AndNotExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$AndNotExpr.html>`__ | `BitwiseBinaryExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BitwiseBinaryExpr.html>`__ |
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+
Type expressions
~~~~~~~~~~~~~~~~
These classes represent different expressions for types. They do
not have a common superclass.
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses |
+=========================================================================================================================================================================================================+====================================================================================================================+====================================================================================================+
| ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `ArrayTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ArrayTypeExpr.html>`__ | |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``struct { ... }`` | `StructTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StructTypeExpr.html>`__ | |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``func`` `FunctionName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FunctionName.html>`__\ ``(...) (...)`` | `FuncTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FuncTypeExpr.html>`__ | |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``interface { ... }`` | `InterfaceTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$InterfaceTypeExpr.html>`__ | |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``map[``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``]``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `MapTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$MapTypeExpr.html>`__ | |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``chan<-`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `SendChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SendChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``<-chan`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `RecvChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$RecvChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| ``chan`` `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | `SendRecvChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SendRecvChanTypeExpr.html>`__ | `ChanTypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ChanTypeExpr.html>`__ |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
Name expressions
~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of
`Name <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Name.html>`__.
The following classes relate to the structure of the name.
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses |
+===================================================================================================================================================================================+======================================================================================================+====================================================================================================+
| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `SimpleName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SimpleName.html>`__ | `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__\ ``.``\ `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `QualifiedName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$QualifiedName.html>`__ | `SelectorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SelectorExpr.html>`__ |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------+
The following classes relate to what sort of entity the name refers to.
- `PackageName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$PackageName.html>`__
- `TypeName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeName.html>`__
- `LabelName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$LabelName.html>`__
- `ValueName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ValueName.html>`__
- `ConstantName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ConstantName.html>`__
- `VariableName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$VariableName.html>`__
- `FunctionName <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$FunctionName.html>`__
Miscellaneous
~~~~~~~~~~~~~
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+============================================================================================================================================================================================================================================================================================================================================================================+========================================================================================================+====================================================================================================================+==========================================================================================================================================================================================================================+
| ``foo`` | `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``_`` | `BlankIdent <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BlankIdent.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``...`` | `Ellipsis <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ellipsis.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``(``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``)`` | `ParenExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ParenExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__\ ``.``\ `Ident <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Ident.html>`__ | `SelectorExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SelectorExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` | `IndexExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$IndexExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``[``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``]`` | `SliceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$SliceExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``.(``\ `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``)`` | `TypeAssertExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeAssertExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ``*``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `StarExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$StarExpr.html>`__ | | can be a `ValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ValueExpr.html>`__ or `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ depending on context |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``:`` `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ | `KeyValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$KeyValueExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__\ ``(``\ `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``)`` | `ConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ConversionExpr.html>`__ | `CallOrConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallOrConversionExpr.html>`__ | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `Expr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__\ ``(...)`` | `CallExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallExpr.html>`__ | `CallOrConversionExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$CallOrConversionExpr.html>`__ | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| (anything unparseable) | `BadExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BadExpr.html>`__ | | |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The following classes organize expressions by the kind of entity they refer to.
+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| CodeQL class | Explanation |
+======================================================================================================+=========================================================================================================================================================================================================================================================+
| `TypeExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$TypeExpr.html>`__ | an expression that denotes a type |
+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `ReferenceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ReferenceExpr.html>`__ | an expression that refers to a variable, a constant, a function, a field, or an element of an array or a slice |
+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| `ValueExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$BadExpr.html>`__ | an expression that can be evaluated to a value (as opposed to expressions that refer to a package, a type, or a statement label). This generalizes `ReferenceExpr <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$ReferenceExpr.html>`__ |
+------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Further reading
---------------
.. include:: ../../reusables/go-further-reading.rst
.. include:: ../../reusables/codeql-ref-tools-further-reading.rst

View File

@@ -99,9 +99,8 @@ The most important subclasses of `AstNode
statements and expressions, respectively. This section briefly discusses some of their more statements and expressions, respectively. This section briefly discusses some of their more
important subclasses and predicates. For a full reference of all the subclasses of `Stmt important subclasses and predicates. For a full reference of all the subclasses of `Stmt
<https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr <https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr
<https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__ and their API, see <https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, see
`Stmt.qll <https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/module.Stmt.html>`__ and `Expr.qll :doc:`Abstract syntax tree classes for Go <ast-class-reference>`.
<https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/module.Expr.html>`__.
Statements Statements
~~~~~~~~~~ ~~~~~~~~~~

View File

@@ -0,0 +1,122 @@
Modeling data flow in Go libraries
==================================
When analyzing a Go program, CodeQL does not examine the source code for
external packages. To track the flow of untrusted data through a library, you
can create a model of the library.
You can find existing models in the ``ql/src/semmle/go/frameworks/`` folder of the
`CodeQL for Go repository <https://github.com/github/codeql-go/tree/main/ql/src/semmle/go/frameworks>`__.
To add a new model, you should make a new file in that folder, named after the library.
Sources
-------
To mark a source of data that is controlled by an untrusted user, we
create a class extending ``UntrustedFlowSource::Range``. Inheritance and
the characteristic predicate of the class should be used to specify
exactly the dataflow node that introduces the data. Here is a short
example from ``Mux.qll``.
.. code-block:: ql
class RequestVars extends DataFlow::UntrustedFlowSource::Range, DataFlow::CallNode {
RequestVars() { this.getTarget().hasQualifiedName("github.com/gorilla/mux", "Vars") }
}
This has the effect that all calls to `the function Vars from the
package mux <http://www.gorillatoolkit.org/pkg/mux#Vars>`__ are
treated as sources of untrusted data.
Flow propagation
----------------
By default, we assume that all functions in libraries do not have
any data flow. To indicate that a particular function does have data flow,
create a class extending ``TaintTracking::FunctionModel`` (or
``DataFlow::FunctionModel`` if the untrusted user data is passed on
without being modified).
Inheritance and the characteristic predicate of the class should specify
the function. The class should also have a member predicate with the signature
``override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp)``
(or
``override predicate hasDataFlow(FunctionInput inp, FunctionOutput outp)``
if extending ``DataFlow::FunctionModel``). The body should constrain
``inp`` and ``outp``.
``FunctionInput`` is an abstract representation of the inputs to a
function. The options are:
* the receiver (``inp.isReceiver()``)
* one of the parameters (``inp.isParameter(i)``)
* one of the results (``inp.isResult(i)``, or ``inp.isResult`` if there is only one result)
Note that it may seem strange that the result of a function could be
considered as a function input, but it is needed in some cases. For
instance, the function ``bufio.NewWriter`` returns a writer ``bw`` that
buffers write operations to an underlying writer ``w``. If tainted data
is written to ``bw``, then it makes sense to propagate that taint back
to the underlying writer ``w``, which can be modeled by saying that
``bufio.NewWriter`` propagates taint from its result to its first
argument.
Similarly, ``FunctionOutput`` is an abstract representation of the
outputs to a function. The options are:
* the receiver (``outp.isReceiver()``)
* one of the parameters (``outp.isParameter(i)``)
* one of the results (``outp.isResult(i)``, or ``outp.isResult`` if there is only one result)
Here is an example from ``Gin.qll``, which has been slightly simplified.
.. code-block:: ql
private class ParamsGet extends TaintTracking::FunctionModel, Method {
ParamsGet() { this.hasQualifiedName("github.com/gin-gonic/gin", "Params", "Get") }
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
inp.isReceiver() and outp.isResult(0)
}
}
This has the effect that calls to the ``Get`` method with receiver type
``Params`` from the ``gin-gonic/gin`` package allow taint to flow from
the receiver to the first result. In other words, if ``p`` has type
``Params`` and taint can flow to it, then after the line
``x := p.Get("foo")`` taint can also flow to ``x``.
Sanitizers
----------
It is not necessary to indicate that library functions are sanitizers.
Their bodies are not analyzed, so it is assumed that data does not
flow through them.
Sinks
-----
Data-flow sinks are specified by queries rather than by library models.
However, you can use library models to indicate when functions belong to
special categories. Queries can then use these categories when specifying
sinks. Classes representing these special categories are contained in
``ql/src/semmle/go/Concepts.qll`` in the `CodeQL for Go repository
<https://github.com/github/codeql-go/blob/main/ql/src/semmle/go/Concepts.qll>`__.
``Concepts.qll`` includes classes for logger mechanisms,
HTTP response writers, HTTP redirects, and marshaling and unmarshaling
functions.
Here is a short example from ``Stdlib.qll``, which has been slightly simplified.
.. code-block:: ql
private class PrintfCall extends LoggerCall::Range, DataFlow::CallNode {
PrintfCall() { this.getTarget().hasQualifiedName("fmt", ["Print", "Printf", "Println"]) }
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
}
This has the effect that any call to ``Print``, ``Printf``, or
``Println`` in the package ``fmt`` is recognized as a logger call.
Any query that uses logger calls as a sink will then identify when tainted data
has been passed as an argument to ``Print``, ``Printf``, or ``Println``.

View File

@@ -7,7 +7,14 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
:hidden: :hidden:
introduce-libraries-go introduce-libraries-go
ast-class-reference
library-modeling-go
- `Basic Go query <https://lgtm.com/help/lgtm/console/ql-go-basic-example>`__: Learn to write and run a simple CodeQL query using LGTM. - `Basic Go query <https://lgtm.com/help/lgtm/console/ql-go-basic-example>`__: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Go <introduce-libraries-go>`: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go. - :doc:`CodeQL library for Go <introduce-libraries-go>`: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go.
- :doc:`Abstract syntax tree classes for working with Go programs <ast-class-reference>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Go programs.
- :doc:`Modeling data flow in Go libraries <library-modeling-go>`: When analyzing a Go program, CodeQL does not examine the source code for external packages.
To track the flow of untrusted data through a library, you can create a model of the library.

View File

@@ -71,6 +71,7 @@ JavaScript and TypeScript built-in support
sqlite3, Database sqlite3, Database
superagent, Network communicator superagent, Network communicator
underscore, Utility library underscore, Utility library
vue, HTML framework

View File

@@ -578,6 +578,8 @@ private module ControlFlowGraphImpl {
n instanceof Stmt and n instanceof Stmt and
not n instanceof PostOrderNode and not n instanceof PostOrderNode and
not n instanceof SynchronizedStmt not n instanceof SynchronizedStmt
or
result = n and n instanceof SwitchExpr
} }
/** /**