Merge branch 'main' into redsun82/rust-pick-edition

This commit is contained in:
Paolo Tranquilli
2025-04-14 15:19:33 +02:00
committed by GitHub
77 changed files with 1967 additions and 147 deletions

View File

@@ -1,21 +1,28 @@
if (($null -ne $env:LGTM_INDEX_INCLUDE) -or ($null -ne $env:LGTM_INDEX_EXCLUDE) -or ($null -ne $env:LGTM_INDEX_FILTERS)) {
Write-Output 'Path filters set. Passing them through to the JavaScript extractor.'
} else {
Write-Output 'No path filters set. Using the default filters.'
# Note: We're adding the `reusable_workflows` subdirectories to proactively
# record workflows that were called cross-repo, check them out locally,
# and enable an interprocedural analysis across the workflow files.
# These workflows follow the convention `.github/reusable_workflows/<nwo>/*.ya?ml`
$DefaultPathFilters = @(
'exclude:**/*',
'include:.github/workflows/*.yml',
'include:.github/workflows/*.yaml',
'include:.github/reusable_workflows/**/*.yml',
'include:.github/reusable_workflows/**/*.yaml',
'include:**/action.yml',
'include:**/action.yaml'
)
# Note: We're adding the `reusable_workflows` subdirectories to proactively
# record workflows that were called cross-repo, check them out locally,
# and enable an interprocedural analysis across the workflow files.
# These workflows follow the convention `.github/reusable_workflows/<nwo>/*.ya?ml`
$DefaultPathFilters = @(
'exclude:**/*',
'include:.github/workflows/*.yml',
'include:.github/workflows/*.yaml',
'include:.github/reusable_workflows/**/*.yml',
'include:.github/reusable_workflows/**/*.yaml',
'include:**/action.yml',
'include:**/action.yaml'
)
if ($null -ne $env:LGTM_INDEX_FILTERS) {
Write-Output 'LGTM_INDEX_FILTERS set. Using the default filters together with the user-provided filters, and passing through to the JavaScript extractor.'
# Begin with the default path inclusions only,
# followed by the user-provided filters.
# If the user provided `paths`, those patterns override the default inclusions
# (because `LGTM_INDEX_FILTERS` will begin with `exclude:**/*`).
# If the user provided `paths-ignore`, those patterns are excluded.
$PathFilters = ($DefaultPathFilters -join "`n") + "`n" + $env:LGTM_INDEX_FILTERS
$env:LGTM_INDEX_FILTERS = $PathFilters
} else {
Write-Output 'LGTM_INDEX_FILTERS not set. Using the default filters, and passing through to the JavaScript extractor.'
$env:LGTM_INDEX_FILTERS = $DefaultPathFilters -join "`n"
}

View File

@@ -17,10 +17,22 @@ include:**/action.yaml
END
)
if [ -n "${LGTM_INDEX_INCLUDE:-}" ] || [ -n "${LGTM_INDEX_EXCLUDE:-}" ] || [ -n "${LGTM_INDEX_FILTERS:-}" ] ; then
echo "Path filters set. Passing them through to the JavaScript extractor."
if [ -n "${LGTM_INDEX_FILTERS:-}" ]; then
echo "LGTM_INDEX_FILTERS set. Using the default filters together with the user-provided filters, and passing through to the JavaScript extractor."
# Begin with the default path inclusions only,
# followed by the user-provided filters.
# If the user provided `paths`, those patterns override the default inclusions
# (because `LGTM_INDEX_FILTERS` will begin with `exclude:**/*`).
# If the user provided `paths-ignore`, those patterns are excluded.
PATH_FILTERS="$(cat << END
${DEFAULT_PATH_FILTERS}
${LGTM_INDEX_FILTERS}
END
)"
LGTM_INDEX_FILTERS="${PATH_FILTERS}"
export LGTM_INDEX_FILTERS
else
echo "No path filters set. Using the default filters."
echo "LGTM_INDEX_FILTERS not set. Using the default filters, and passing through to the JavaScript extractor."
LGTM_INDEX_FILTERS="${DEFAULT_PATH_FILTERS}"
export LGTM_INDEX_FILTERS
fi

View File

@@ -1,2 +0,0 @@
def test(codeql, actions):
codeql.database.create(source_root="src")

View File

@@ -0,0 +1,6 @@
| src/.github/action.yaml:1:1:11:32 | name: ' ... action' |
| src/.github/actions/action-name/action.yml:1:1:11:32 | name: ' ... action' |
| src/.github/workflows/workflow.yml:1:1:12:33 | name: A workflow |
| src/action.yml:1:1:11:32 | name: ' ... action' |
| src/excluded/action.yml:1:1:11:32 | name: ' ... action' |
| src/included/action.yml:1:1:11:32 | name: ' ... action' |

View File

@@ -0,0 +1,2 @@
| src/included/action.yml:1:1:11:32 | name: ' ... action' |
| src/included/unreachable-workflow.yml:1:1:12:33 | name: A ... orkflow |

View File

@@ -2,3 +2,4 @@
| src/.github/actions/action-name/action.yml:1:1:11:32 | name: ' ... action' |
| src/.github/workflows/workflow.yml:1:1:12:33 | name: A workflow |
| src/action.yml:1:1:11:32 | name: ' ... action' |
| src/included/action.yml:1:1:11:32 | name: ' ... action' |

View File

@@ -0,0 +1,2 @@
| src/included/action.yml:1:1:11:32 | name: ' ... action' |
| src/included/unreachable-workflow.yml:1:1:12:33 | name: A ... orkflow |

View File

@@ -0,0 +1,5 @@
import actions
from AstNode n
where n instanceof Workflow or n instanceof CompositeAction
select n

View File

@@ -0,0 +1,4 @@
paths:
- 'included'
paths-ignore:
- 'excluded'

View File

@@ -0,0 +1,2 @@
paths-ignore:
- 'excluded'

View File

@@ -0,0 +1,2 @@
paths:
- 'included'

View File

@@ -0,0 +1,6 @@
src/.github/action.yaml
src/.github/actions/action-name/action.yml
src/.github/workflows/workflow.yml
src/action.yml
src/excluded/action.yml
src/included/action.yml

View File

@@ -0,0 +1,3 @@
src/included/action.yml
src/included/not-an-action.yml
src/included/unreachable-workflow.yml

View File

@@ -0,0 +1,5 @@
src/.github/action.yaml
src/.github/actions/action-name/action.yml
src/.github/workflows/workflow.yml
src/action.yml
src/included/action.yml

View File

@@ -0,0 +1,3 @@
src/included/action.yml
src/included/not-an-action.yml
src/included/unreachable-workflow.yml

View File

@@ -0,0 +1,11 @@
name: 'A composite action'
description: 'Do something'
runs:
using: "composite"
steps:
- name: Print
run: echo "Hello world"
shell: bash
- name: Checkout
uses: actions/checkout@v4

View File

@@ -0,0 +1,11 @@
name: 'A composite action'
description: 'Do something'
runs:
using: "composite"
steps:
- name: Print
run: echo "Hello world"
shell: bash
- name: Checkout
uses: actions/checkout@v4

View File

@@ -0,0 +1 @@
name: 'Not an action, just a YAML file'

View File

@@ -0,0 +1,12 @@
name: An unreachable workflow
on:
push:
branches:
- main
jobs:
job:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -0,0 +1,12 @@
name: An unreachable workflow
on:
push:
branches:
- main
jobs:
job:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

View File

@@ -0,0 +1,18 @@
import pytest
@pytest.mark.ql_test(expected=".default-filters.expected")
def test_default_filters(codeql, actions, check_source_archive):
check_source_archive.expected_suffix = ".default-filters.expected"
codeql.database.create(source_root="src")
@pytest.mark.ql_test(expected=".paths-only.expected")
def test_config_paths_only(codeql, actions):
codeql.database.create(source_root="src", codescanning_config="codeql-config.paths-only.yml")
@pytest.mark.ql_test(expected=".paths-ignore-only.expected")
def test_config_paths_ignore_only(codeql, actions):
codeql.database.create(source_root="src", codescanning_config="codeql-config.paths-ignore-only.yml")
@pytest.mark.ql_test(expected=".paths-and-paths-ignore.expected")
def test_config_paths_and_paths_ignore(codeql, actions):
codeql.database.create(source_root="src", codescanning_config="codeql-config.paths-and-paths-ignore.yml")

View File

@@ -465,7 +465,7 @@ private predicate isFunctionConstructedFrom(Function f, Function templateFunc) {
}
/** Gets the fully templated version of `f`. */
private Function getFullyTemplatedFunction(Function f) {
Function getFullyTemplatedFunction(Function f) {
not f.isFromUninstantiatedTemplate(_) and
(
exists(Class c, Class templateClass, int i |
@@ -559,12 +559,15 @@ private string getTypeName(Type t, boolean needsSpace) {
/**
* Gets a type name for the `n`'th parameter of `f` without any template
* arguments. The result may be a string representing a type for which the
* typedefs have been resolved.
* arguments.
*
* If `canonical = false` then the result may be a string representing a type
* for which the typedefs have been resolved. If `canonical = true` then the
* result will be a string representing a type without resolving `typedefs`.
*/
bindingset[f]
pragma[inline_late]
string getParameterTypeWithoutTemplateArguments(Function f, int n) {
string getParameterTypeWithoutTemplateArguments(Function f, int n, boolean canonical) {
exists(string s, string base, string specifiers, Type t |
t = f.getParameter(n).getType() and
// The name of the string can either be the possibly typedefed name
@@ -572,14 +575,19 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
// `getTypeName(t, _)` is almost equal to `t.resolveTypedefs().getName()`,
// except that `t.resolveTypedefs()` doesn't have a result when the
// resulting type doesn't appear in the database.
s = [t.getName(), getTypeName(t, _)] and
(
s = t.getName() and canonical = true
or
s = getTypeName(t, _) and canonical = false
) and
parseAngles(s, base, _, specifiers) and
result = base + specifiers
)
or
f.isVarargs() and
n = f.getNumberOfParameters() and
result = "..."
result = "..." and
canonical = true
}
/**
@@ -590,7 +598,7 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
exists(Function templateFunction |
templateFunction = getFullyTemplatedFunction(f) and
remaining = templateFunction.getNumberOfTemplateArguments() and
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
result = getParameterTypeWithoutTemplateArguments(templateFunction, n, _)
)
or
exists(string mid, TypeTemplateParameter tp, Function templateFunction |
@@ -627,7 +635,7 @@ private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining
}
/** Gets the string representation of the `i`'th parameter of `c`. */
private string getParameterTypeName(Function c, int i) {
string getParameterTypeName(Function c, int i) {
result = getTypeNameWithoutClassTemplates(c, i, 0)
}

View File

@@ -371,7 +371,7 @@ private class PrimaryArgumentNode extends ArgumentNode, OperandNode {
PrimaryArgumentNode() { exists(CallInstruction call | op = call.getAnArgumentOperand()) }
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
op = call.getArgumentOperand(pos.(DirectPosition).getIndex())
op = call.getArgumentOperand(pos.(DirectPosition).getArgumentIndex())
}
}
@@ -410,8 +410,16 @@ class ParameterPosition = Position;
class ArgumentPosition = Position;
abstract class Position extends TPosition {
/** Gets a textual representation of this position. */
abstract string toString();
/**
* Gets the argument index of this position. The qualifier of a call has
* argument index `-1`.
*/
abstract int getArgumentIndex();
/** Gets the indirection index of this position. */
abstract int getIndirectionIndex();
}
@@ -428,7 +436,7 @@ class DirectPosition extends Position, TDirectPosition {
result = index.toString()
}
int getIndex() { result = index }
override int getArgumentIndex() { result = index }
final override int getIndirectionIndex() { result = 0 }
}
@@ -445,16 +453,29 @@ class IndirectionPosition extends Position, TIndirectionPosition {
else result = repeatStars(indirectionIndex) + argumentIndex.toString()
}
int getArgumentIndex() { result = argumentIndex }
override int getArgumentIndex() { result = argumentIndex }
final override int getIndirectionIndex() { result = indirectionIndex }
}
newtype TPosition =
TDirectPosition(int argumentIndex) { exists(any(CallInstruction c).getArgument(argumentIndex)) } or
TDirectPosition(int argumentIndex) {
exists(any(CallInstruction c).getArgument(argumentIndex))
or
// Handle the rare case where there is a function definition but no call to
// the function.
exists(any(Cpp::Function f).getParameter(argumentIndex))
} or
TIndirectionPosition(int argumentIndex, int indirectionIndex) {
Ssa::hasIndirectOperand(any(CallInstruction call).getArgumentOperand(argumentIndex),
indirectionIndex)
or
// Handle the rare case where there is a function definition but no call to
// the function.
exists(Cpp::Function f, Cpp::Parameter p |
p = f.getParameter(argumentIndex) and
indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(p.getUnspecifiedType()) - 1]
)
}
private newtype TReturnKind =
@@ -501,6 +522,15 @@ class ReturnKind extends TReturnKind {
/** Gets a textual representation of this return kind. */
abstract string toString();
/** Holds if this `ReturnKind` is generated from a `return` statement. */
abstract predicate isNormalReturn();
/**
* Holds if this `ReturnKind` is generated from a write to the parameter with
* index `argumentIndex`
*/
abstract predicate isIndirectReturn(int argumentIndex);
}
/**
@@ -514,6 +544,10 @@ class NormalReturnKind extends ReturnKind, TNormalReturnKind {
override int getIndirectionIndex() { result = indirectionIndex }
override string toString() { result = "indirect return" }
override predicate isNormalReturn() { any() }
override predicate isIndirectReturn(int argumentIndex) { none() }
}
/**
@@ -528,6 +562,10 @@ private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind {
override int getIndirectionIndex() { result = indirectionIndex }
override string toString() { result = "indirect outparam[" + argumentIndex.toString() + "]" }
override predicate isNormalReturn() { none() }
override predicate isIndirectReturn(int argumentIndex_) { argumentIndex_ = argumentIndex }
}
/** A data flow node that occurs as the result of a `ReturnStmt`. */

View File

@@ -1445,7 +1445,7 @@ private class ExplicitParameterInstructionNode extends AbstractExplicitParameter
ExplicitParameterInstructionNode() { exists(instr.getParameter()) }
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
f.getParameter(pos.(DirectPosition).getIndex()) = instr.getParameter()
f.getParameter(pos.(DirectPosition).getArgumentIndex()) = instr.getParameter()
}
override string toStringImpl() { result = instr.getParameter().toString() }
@@ -1460,7 +1460,7 @@ class ThisParameterInstructionNode extends AbstractExplicitParameterNode,
ThisParameterInstructionNode() { instr.getIRVariable() instanceof IRThisVariable }
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
pos.(DirectPosition).getIndex() = -1 and
pos.(DirectPosition).getArgumentIndex() = -1 and
instr.getEnclosingFunction() = f
}
@@ -1494,7 +1494,7 @@ private class DirectBodyLessParameterNode extends AbstractExplicitParameterNode,
override predicate isSourceParameterOf(Function f, ParameterPosition pos) {
this.getFunction() = f and
f.getParameter(pos.(DirectPosition).getIndex()) = p
f.getParameter(pos.(DirectPosition).getArgumentIndex()) = p
}
override Parameter getParameter() { result = p }

View File

@@ -229,11 +229,11 @@ private module SpeculativeTaintFlow {
not exists(DataFlowDispatch::viableCallable(call)) and
src.(DataFlowPrivate::ArgumentNode).argumentOf(call, argpos)
|
not argpos.(DirectPosition).getIndex() = -1 and
not argpos.(DirectPosition).getArgumentIndex() = -1 and
sink.(PostUpdateNode)
.getPreUpdateNode()
.(DataFlowPrivate::ArgumentNode)
.argumentOf(call, any(DirectPosition qualpos | qualpos.getIndex() = -1))
.argumentOf(call, any(DirectPosition qualpos | qualpos.getArgumentIndex() = -1))
or
sink.(DataFlowPrivate::OutNode).getCall() = call
)

View File

@@ -424,8 +424,7 @@ namespace Semmle.Autobuild.CSharp.Tests
return new CSharpAutobuilder(actions, options);
}
[Fact]
public void TestDefaultCSharpAutoBuilder()
private void SetupActionForDotnet()
{
actions.RunProcess["cmd.exe /C dotnet --info"] = 0;
actions.RunProcess[@"cmd.exe /C dotnet clean C:\Project\test.csproj"] = 0;
@@ -438,20 +437,80 @@ namespace Semmle.Autobuild.CSharp.Tests
actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SCRATCH_DIR"] = "scratch";
actions.EnumerateFiles[@"C:\Project"] = "foo.cs\nbar.cs\ntest.csproj";
actions.EnumerateDirectories[@"C:\Project"] = "";
var xml = new XmlDocument();
xml.LoadXml(@"<Project Sdk=""Microsoft.NET.Sdk"">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
}
</Project>");
private void CreateAndVerifyDotnetScript(XmlDocument xml)
{
actions.LoadXml[@"C:\Project\test.csproj"] = xml;
var autobuilder = CreateAutoBuilder(true);
TestAutobuilderScript(autobuilder, 0, 4);
}
[Fact]
public void TestDefaultCSharpAutoBuilder1()
{
SetupActionForDotnet();
var xml = new XmlDocument();
xml.LoadXml(
"""
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
</Project>
""");
CreateAndVerifyDotnetScript(xml);
}
[Fact]
public void TestDefaultCSharpAutoBuilder2()
{
SetupActionForDotnet();
var xml = new XmlDocument();
xml.LoadXml(
"""
<Project>
<Sdk Name="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
"""
);
CreateAndVerifyDotnetScript(xml);
}
[Fact]
public void TestDefaultCSharpAutoBuilder3()
{
SetupActionForDotnet();
var xml = new XmlDocument();
xml.LoadXml(
"""
<Project>
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>
"""
);
CreateAndVerifyDotnetScript(xml);
}
[Fact]
public void TestLinuxCSharpAutoBuilder()
{

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Semmle.Util.Logging;
namespace Semmle.Autobuild.Shared
{
@@ -26,6 +25,26 @@ namespace Semmle.Autobuild.Shared
private readonly Lazy<List<Project<TAutobuildOptions>>> includedProjectsLazy;
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjectsLazy.Value;
private static bool HasSdkAttribute(XmlElement xml) =>
xml.HasAttribute("Sdk");
private static bool AnyElement(XmlNodeList l, Func<XmlElement, bool> f) =>
l.OfType<XmlElement>().Any(f);
/// <summary>
/// According to https://learn.microsoft.com/en-us/visualstudio/msbuild/how-to-use-project-sdk?view=vs-2022#reference-a-project-sdk
/// there are three ways to reference a project SDK:
/// 1. As an attribute on the <Project/>.
/// 2. As a top level element of <Project>.
/// 3. As an attribute on an <Import> element.
///
/// Returns true, if the Sdk attribute is used, otherwise false.
/// </summary>
private static bool ReferencesSdk(XmlElement xml) =>
HasSdkAttribute(xml) || // Case 1
AnyElement(xml.ChildNodes, e => e.Name == "Sdk") || // Case 2
AnyElement(xml.GetElementsByTagName("Import"), HasSdkAttribute); // Case 3
public Project(Autobuilder<TAutobuildOptions> builder, string path) : base(builder, path)
{
ToolsVersion = new Version();
@@ -49,7 +68,7 @@ namespace Semmle.Autobuild.Shared
if (root?.Name == "Project")
{
if (root.HasAttribute("Sdk"))
if (ReferencesSdk(root))
{
DotNetProject = true;
return;

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Improved autobuilder logic for detecting whether a project references a SDK (and should be built using `dotnet`).

View File

@@ -22,10 +22,16 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CsharpDat
class Callable = CS::Callable;
class NodeExtended extends CS::DataFlow::Node {
Callable getAsExprEnclosingCallable() { result = this.asExpr().getEnclosingCallable() }
class NodeExtended = CS::DataFlow::Node;
Callable getAsExprEnclosingCallable(NodeExtended node) {
result = node.asExpr().getEnclosingCallable()
}
Callable getEnclosingCallable(NodeExtended node) { result = node.getEnclosingCallable() }
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
/**
* Holds if any of the parameters of `api` are `System.Func<>`.
*/

View File

@@ -32,10 +32,16 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, JavaDataF
class Callable = J::Callable;
class NodeExtended extends DataFlow::Node {
Callable getAsExprEnclosingCallable() { result = this.asExpr().getEnclosingCallable() }
class NodeExtended = DataFlow::Node;
Callable getAsExprEnclosingCallable(NodeExtended node) {
result = node.asExpr().getEnclosingCallable()
}
Callable getEnclosingCallable(NodeExtended node) { result = node.getEnclosingCallable() }
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
private predicate isInfrequentlyUsed(J::CompilationUnit cu) {
cu.getPackage().getName().matches("javax.swing%") or
cu.getPackage().getName().matches("java.awt%")

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Data passed to the [NextResponse](https://nextjs.org/docs/app/api-reference/functions/next-response) constructor is now treated as a sink for `js/reflected-xss`.
* Data received from [NextRequest](https://nextjs.org/docs/app/api-reference/functions/next-request) and [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) is now treated as a remote user input `source`.

View File

@@ -213,10 +213,12 @@ module NextJS {
/**
* Gets a folder that contains API endpoints for a Next.js application.
* These API endpoints act as Express-like route-handlers.
* It matches both the Pages Router (`pages/api/`) Next.js 12 or earlier and
* the App Router (`app/api/`) Next.js 13+ structures.
*/
Folder apiFolder() {
result = getANextPackage().getFile().getParentContainer().getFolder("pages").getFolder("api")
or
result =
getANextPackage().getFile().getParentContainer().getFolder(["pages", "app"]).getFolder("api") or
result = apiFolder().getAFolder()
}
@@ -271,4 +273,64 @@ module NextJS {
override string getCredentialsKind() { result = "jwt key" }
}
}
/**
* A route handler for Next.js 13+ App Router API endpoints, which are defined by exporting
* HTTP method functions (like `GET`, `POST`, `PUT`, `DELETE`) from route.js files inside
* the `app/api/` directory.
*/
class NextAppRouteHandler extends DataFlow::FunctionNode, Http::Servers::StandardRouteHandler {
NextAppRouteHandler() {
exists(Module mod |
mod.getFile().getParentContainer() = apiFolder() or
mod.getFile().getStem() = "middleware"
|
this =
mod.getAnExportedValue([any(Http::RequestMethodName m), "middleware"]).getAFunctionValue()
)
}
/**
* Gets the request parameter, which is either a `NextRequest` object (from `next/server`) or a standard web `Request` object.
*/
DataFlow::SourceNode getRequest() { result = this.getParameter(0) }
}
/**
* A source of user-controlled data from a `NextRequest` object (from `next/server`) or a standard web `Request` object
* in a Next.js App Router route handler.
*/
class NextAppRequestSource extends Http::RequestInputAccess {
NextAppRouteHandler handler;
string kind;
NextAppRequestSource() {
(
this =
handler.getRequest().getAMethodCall(["json", "formData", "blob", "arrayBuffer", "text"])
or
this = handler.getRequest().getAPropertyRead("body")
) and
kind = "body"
or
this = handler.getRequest().getAPropertyRead(["url", "nextUrl"]) and
kind = "url"
or
this =
handler
.getRequest()
.getAPropertyRead("nextUrl")
.getAPropertyRead("searchParams")
.getAMemberCall("get") and
kind = "parameter"
or
this = handler.getRequest().getAPropertyRead("headers") and kind = "headers"
}
override string getKind() { result = kind }
override Http::RouteHandler getRouteHandler() { result = handler }
override string getSourceType() { result = "Next.js App Router request" }
}
}

View File

@@ -19,10 +19,13 @@ private class HeadersEntryPoint extends API::EntryPoint {
}
/**
* A call to the `Response` constructor.
* A call to the `Response` and `NextResponse` constructor.
*/
private class ResponseCall extends API::InvokeNode {
ResponseCall() { this = any(ResponseEntryPoint e).getANode().getAnInstantiation() }
ResponseCall() {
this = any(ResponseEntryPoint e).getANode().getAnInstantiation() or
this = API::moduleImport("next/server").getMember("NextResponse").getAnInstantiation()
}
}
/**

View File

@@ -27,6 +27,14 @@
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to a $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
| ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to a $@. | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | user-provided value |
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | ReflectedXssGood3.js:135:15:135:27 | req.params.id | ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to a $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
| app/api/route.ts:5:18:5:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:5:18:5:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:13:18:13:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:13:18:13:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:25:18:25:21 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:25:18:25:21 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:29:25:29:28 | body | app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:29:25:29:28 | body | Cross-site scripting vulnerability due to a $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:7:20:7:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:7:20:7:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:15:20:15:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:27:20:27:23 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:31:27:31:30 | body | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to a $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| etherpad.js:11:12:11:19 | response | etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:11:12:11:19 | response | Cross-site scripting vulnerability due to a $@. | etherpad.js:9:16:9:30 | req.query.jsonp | user-provided value |
| formatting.js:6:14:6:47 | util.fo ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to a $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
| formatting.js:7:14:7:53 | require ... , evil) | formatting.js:4:16:4:29 | req.query.evil | formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to a $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
@@ -128,6 +136,18 @@ edges
| ReflectedXssGood3.js:135:15:135:27 | req.params.id | ReflectedXssGood3.js:135:9:135:27 | url | provenance | |
| ReflectedXssGood3.js:139:24:139:26 | url | ReflectedXssGood3.js:68:22:68:26 | value | provenance | |
| ReflectedXssGood3.js:139:24:139:26 | url | ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | provenance | |
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:5:18:5:21 | body | provenance | |
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:13:18:13:21 | body | provenance | |
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:25:18:25:21 | body | provenance | |
| app/api/route.ts:2:11:2:33 | body | app/api/route.ts:29:25:29:28 | body | provenance | |
| app/api/route.ts:2:18:2:33 | await req.json() | app/api/route.ts:2:11:2:33 | body | provenance | |
| app/api/route.ts:2:24:2:33 | req.json() | app/api/route.ts:2:18:2:33 | await req.json() | provenance | |
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:7:20:7:23 | body | provenance | |
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:15:20:15:23 | body | provenance | |
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:27:20:27:23 | body | provenance | |
| app/api/routeNextRequest.ts:4:9:4:31 | body | app/api/routeNextRequest.ts:31:27:31:30 | body | provenance | |
| app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | app/api/routeNextRequest.ts:4:9:4:31 | body | provenance | |
| app/api/routeNextRequest.ts:4:22:4:31 | req.json() | app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | provenance | |
| etherpad.js:9:5:9:53 | response | etherpad.js:11:12:11:19 | response | provenance | |
| etherpad.js:9:16:9:30 | req.query.jsonp | etherpad.js:9:5:9:53 | response | provenance | |
| formatting.js:4:9:4:29 | evil | formatting.js:6:43:6:46 | evil | provenance | |
@@ -309,6 +329,20 @@ nodes
| ReflectedXssGood3.js:135:15:135:27 | req.params.id | semmle.label | req.params.id |
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | semmle.label | escapeHtml3(url) |
| ReflectedXssGood3.js:139:24:139:26 | url | semmle.label | url |
| app/api/route.ts:2:11:2:33 | body | semmle.label | body |
| app/api/route.ts:2:18:2:33 | await req.json() | semmle.label | await req.json() |
| app/api/route.ts:2:24:2:33 | req.json() | semmle.label | req.json() |
| app/api/route.ts:5:18:5:21 | body | semmle.label | body |
| app/api/route.ts:13:18:13:21 | body | semmle.label | body |
| app/api/route.ts:25:18:25:21 | body | semmle.label | body |
| app/api/route.ts:29:25:29:28 | body | semmle.label | body |
| app/api/routeNextRequest.ts:4:9:4:31 | body | semmle.label | body |
| app/api/routeNextRequest.ts:4:16:4:31 | await req.json() | semmle.label | await req.json() |
| app/api/routeNextRequest.ts:4:22:4:31 | req.json() | semmle.label | req.json() |
| app/api/routeNextRequest.ts:7:20:7:23 | body | semmle.label | body |
| app/api/routeNextRequest.ts:15:20:15:23 | body | semmle.label | body |
| app/api/routeNextRequest.ts:27:20:27:23 | body | semmle.label | body |
| app/api/routeNextRequest.ts:31:27:31:30 | body | semmle.label | body |
| etherpad.js:9:5:9:53 | response | semmle.label | response |
| etherpad.js:9:16:9:30 | req.query.jsonp | semmle.label | req.query.jsonp |
| etherpad.js:11:12:11:19 | response | semmle.label | response |

View File

@@ -26,6 +26,14 @@
| ReflectedXssContentTypes.js:39:13:39:35 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:39:23:39:35 | req.params.id | user-provided value |
| ReflectedXssContentTypes.js:70:12:70:34 | "FOO: " ... rams.id | Cross-site scripting vulnerability due to $@. | ReflectedXssContentTypes.js:70:22:70:34 | req.params.id | user-provided value |
| ReflectedXssGood3.js:139:12:139:27 | escapeHtml3(url) | Cross-site scripting vulnerability due to $@. | ReflectedXssGood3.js:135:15:135:27 | req.params.id | user-provided value |
| app/api/route.ts:5:18:5:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:13:18:13:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:25:18:25:21 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/route.ts:29:25:29:28 | body | Cross-site scripting vulnerability due to $@. | app/api/route.ts:2:24:2:33 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:7:20:7:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:15:20:15:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:27:20:27:23 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| app/api/routeNextRequest.ts:31:27:31:30 | body | Cross-site scripting vulnerability due to $@. | app/api/routeNextRequest.ts:4:22:4:31 | req.json() | user-provided value |
| formatting.js:6:14:6:47 | util.fo ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
| formatting.js:7:14:7:53 | require ... , evil) | Cross-site scripting vulnerability due to $@. | formatting.js:4:16:4:29 | req.query.evil | user-provided value |
| live-server.js:6:13:6:50 | `<html> ... /html>` | Cross-site scripting vulnerability due to $@. | live-server.js:4:21:4:27 | req.url | user-provided value |

View File

@@ -0,0 +1,30 @@
export async function POST(req: Request) {
const body = await req.json(); // $ Source
new Response(body, {headers: { 'Content-Type': 'application/json' }});
new Response(body, {headers: { 'Content-Type': 'text/html' }}); // $ Alert
const headers2 = new Headers(req.headers);
headers2.append('Content-Type', 'application/json');
new Response(body, { headers: headers2 });
const headers3 = new Headers(req.headers);
headers3.append('Content-Type', 'text/html');
new Response(body, { headers: headers3 }); // $ Alert
const headers4 = new Headers({
...Object.fromEntries(req.headers),
'Content-Type': 'application/json'
});
new Response(body, { headers: headers4 });
const headers5 = new Headers({
...Object.fromEntries(req.headers),
'Content-Type': 'text/html'
});
new Response(body, { headers: headers5 }); // $ Alert
const headers = new Headers(req.headers);
headers.set('Content-Type', 'text/html');
return new Response(body, { headers }); // $ Alert
}

View File

@@ -0,0 +1,32 @@
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const body = await req.json(); // $ Source
new NextResponse(body, {headers: { 'Content-Type': 'application/json' }});
new NextResponse(body, {headers: { 'Content-Type': 'text/html' }}); // $ Alert
const headers2 = new Headers(req.headers);
headers2.append('Content-Type', 'application/json');
new NextResponse(body, { headers: headers2 });
const headers3 = new Headers(req.headers);
headers3.append('Content-Type', 'text/html');
new NextResponse(body, { headers: headers3 }); // $ Alert
const headers4 = new Headers({
...Object.fromEntries(req.headers),
'Content-Type': 'application/json'
});
new NextResponse(body, { headers: headers4 });
const headers5 = new Headers({
...Object.fromEntries(req.headers),
'Content-Type': 'text/html'
});
new NextResponse(body, { headers: headers5 }); // $ Alert
const headers = new Headers(req.headers);
headers.set('Content-Type', 'text/html');
return new NextResponse(body, { headers }); // $ Alert
}

View File

@@ -1,2 +0,0 @@
consistencyIssue
resultInWrongFile

View File

@@ -1,25 +0,0 @@
import javascript
import semmle.javascript.security.dataflow.RequestForgeryQuery as RequestForgery
import semmle.javascript.security.dataflow.ClientSideRequestForgeryQuery as ClientSideRequestForgery
deprecated import utils.test.ConsistencyChecking
query predicate resultInWrongFile(DataFlow::Node node) {
exists(string filePattern |
RequestForgery::RequestForgeryFlow::flowTo(node) and
filePattern = ".*serverSide.*"
or
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(node) and
filePattern = ".*clientSide.*"
|
not node.getFile().getRelativePath().regexpMatch(filePattern)
)
}
deprecated class Consistency extends ConsistencyConfiguration {
Consistency() { this = "Consistency" }
override DataFlow::Node getAnAlert() {
RequestForgery::RequestForgeryFlow::flowTo(result) or
ClientSideRequestForgery::ClientSideRequestForgeryFlow::flowTo(result)
}
}

View File

@@ -0,0 +1,5 @@
export async function POST(req: Request) {
const { url } = await req.json(); // $ Source[js/request-forgery]
const res = await fetch(url); // $ Alert[js/request-forgery] Sink[js/request-forgery]
return new Response(res.body, { headers: res.headers });
}

View File

@@ -0,0 +1,8 @@
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const { url } = await req.json(); // $ Source[js/request-forgery]
const res = await fetch(url); // $ Alert[js/request-forgery] Sink[js/request-forgery]
const data = await res.text();
return new NextResponse(data, { headers: res.headers });
}

View File

@@ -0,0 +1,18 @@
import { NextRequest, NextResponse } from 'next/server';
export async function middleware(req: NextRequest) {
const target = req.nextUrl // $ Source[js/request-forgery]
const target2 = target.searchParams.get('target'); // $ Source[js/request-forgery]
if (target) {
const res = await fetch(target) // $ Alert[js/request-forgery] Sink[js/request-forgery]
const data = await res.text()
return new NextResponse(data)
}
if (target2) {
const res = await fetch(target2); // $ Alert[js/request-forgery] Sink[js/request-forgery]
const data = await res.text();
return new NextResponse(data);
}
return NextResponse.next()
}

View File

@@ -0,0 +1,13 @@
{
"name": "next-edge-proxy-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "15.1.7"
}
}

View File

@@ -1,4 +1,8 @@
#select
| Request/app/api/proxy/route2.serverSide.ts:5:21:5:30 | fetch(url) | Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | The $@ of this request depends on a $@. | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | URL | Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | user-provided value |
| Request/app/api/proxy/route.serverSide.ts:3:21:3:30 | fetch(url) | Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | The $@ of this request depends on a $@. | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | URL | Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | user-provided value |
| Request/middleware.ts:7:25:7:37 | fetch(target) | Request/middleware.ts:4:20:4:30 | req.nextUrl | Request/middleware.ts:7:31:7:36 | target | The $@ of this request depends on a $@. | Request/middleware.ts:7:31:7:36 | target | URL | Request/middleware.ts:4:20:4:30 | req.nextUrl | user-provided value |
| Request/middleware.ts:12:27:12:40 | fetch(target2) | Request/middleware.ts:5:21:5:53 | target. ... arget') | Request/middleware.ts:12:33:12:39 | target2 | The $@ of this request depends on a $@. | Request/middleware.ts:12:33:12:39 | target2 | URL | Request/middleware.ts:5:21:5:53 | target. ... arget') | user-provided value |
| apollo.serverSide.ts:8:39:8:64 | get(fil ... => {}) | apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:8:43:8:50 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:8:43:8:50 | file.url | URL | apollo.serverSide.ts:7:36:7:44 | { files } | user-provided value |
| apollo.serverSide.ts:18:37:18:62 | get(fil ... => {}) | apollo.serverSide.ts:17:34:17:42 | { files } | apollo.serverSide.ts:18:41:18:48 | file.url | The $@ of this request depends on a $@. | apollo.serverSide.ts:18:41:18:48 | file.url | URL | apollo.serverSide.ts:17:34:17:42 | { files } | user-provided value |
| axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | The $@ of this request depends on a $@. | axiosInterceptors.serverSide.js:11:26:11:40 | userProvidedUrl | endpoint | axiosInterceptors.serverSide.js:19:21:19:28 | req.body | user-provided value |
@@ -27,6 +31,18 @@
| serverSide.js:125:5:128:6 | axios({ ... \\n }) | serverSide.js:123:29:123:35 | req.url | serverSide.js:127:14:127:20 | tainted | The $@ of this request depends on a $@. | serverSide.js:127:14:127:20 | tainted | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
| serverSide.js:131:5:131:20 | axios.get(myUrl) | serverSide.js:123:29:123:35 | req.url | serverSide.js:131:15:131:19 | myUrl | The $@ of this request depends on a $@. | serverSide.js:131:15:131:19 | myUrl | URL | serverSide.js:123:29:123:35 | req.url | user-provided value |
edges
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | provenance | |
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | provenance | |
| Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | provenance | |
| Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | provenance | |
| Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | provenance | |
| Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | provenance | |
| Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | provenance | |
| Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | provenance | |
| Request/middleware.ts:4:11:4:30 | target | Request/middleware.ts:7:31:7:36 | target | provenance | |
| Request/middleware.ts:4:20:4:30 | req.nextUrl | Request/middleware.ts:4:11:4:30 | target | provenance | |
| Request/middleware.ts:5:11:5:53 | target2 | Request/middleware.ts:12:33:12:39 | target2 | provenance | |
| Request/middleware.ts:5:21:5:53 | target. ... arget') | Request/middleware.ts:5:11:5:53 | target2 | provenance | |
| apollo.serverSide.ts:7:36:7:44 | files | apollo.serverSide.ts:8:13:8:17 | files | provenance | |
| apollo.serverSide.ts:7:36:7:44 | { files } | apollo.serverSide.ts:7:36:7:44 | files | provenance | |
| apollo.serverSide.ts:8:13:8:17 | files | apollo.serverSide.ts:8:28:8:31 | file | provenance | |
@@ -91,6 +107,22 @@ edges
| serverSide.js:130:9:130:45 | myUrl | serverSide.js:131:15:131:19 | myUrl | provenance | |
| serverSide.js:130:37:130:43 | tainted | serverSide.js:130:9:130:45 | myUrl | provenance | |
nodes
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:15 | { url } | semmle.label | { url } |
| Request/app/api/proxy/route2.serverSide.ts:4:9:4:34 | url | semmle.label | url |
| Request/app/api/proxy/route2.serverSide.ts:4:19:4:34 | await req.json() | semmle.label | await req.json() |
| Request/app/api/proxy/route2.serverSide.ts:4:25:4:34 | req.json() | semmle.label | req.json() |
| Request/app/api/proxy/route2.serverSide.ts:5:27:5:29 | url | semmle.label | url |
| Request/app/api/proxy/route.serverSide.ts:2:9:2:15 | { url } | semmle.label | { url } |
| Request/app/api/proxy/route.serverSide.ts:2:9:2:34 | url | semmle.label | url |
| Request/app/api/proxy/route.serverSide.ts:2:19:2:34 | await req.json() | semmle.label | await req.json() |
| Request/app/api/proxy/route.serverSide.ts:2:25:2:34 | req.json() | semmle.label | req.json() |
| Request/app/api/proxy/route.serverSide.ts:3:27:3:29 | url | semmle.label | url |
| Request/middleware.ts:4:11:4:30 | target | semmle.label | target |
| Request/middleware.ts:4:20:4:30 | req.nextUrl | semmle.label | req.nextUrl |
| Request/middleware.ts:5:11:5:53 | target2 | semmle.label | target2 |
| Request/middleware.ts:5:21:5:53 | target. ... arget') | semmle.label | target. ... arget') |
| Request/middleware.ts:7:31:7:36 | target | semmle.label | target |
| Request/middleware.ts:12:33:12:39 | target2 | semmle.label | target2 |
| apollo.serverSide.ts:7:36:7:44 | files | semmle.label | files |
| apollo.serverSide.ts:7:36:7:44 | { files } | semmle.label | { files } |
| apollo.serverSide.ts:8:13:8:17 | files | semmle.label | files |

View File

@@ -0,0 +1,4 @@
---
category: majorAnalysis
---
* The query `rb/uninitialized-local-variable` now only produces alerts when the variable is the receiver of a method call and should produce very few false positives. It also now comes with a help file.

View File

@@ -2,4 +2,5 @@
- include:
id:
- rb/database-query-in-loop
- rb/useless-assignment-to-local
- rb/useless-assignment-to-local
- rb/uninitialized-local-variable

View File

@@ -0,0 +1,41 @@
# Method call on `nil`
## Description
In Ruby, it is not necessary to explicitly initialize variables.
If a local variable has not been explicitly initialized, it will have the value `nil`. If this happens unintended, though, the variable will not represent an object with the expected methods, and a method call on the variable will raise a `NoMethodError`.
## Recommendation
Ensure that the variable cannot be `nil` at the point hightligted by the alert.
This can be achieved by using a safe navigation or adding a check for `nil`.
Note: You do not need to explicitly initialize the variable, if you can make the program deal with the possible `nil` value. In particular, initializing the variable to `nil` will have no effect, as this is already the value of the variable. If `nil` is the only possibly default value, you need to handle the `nil` value instead of initializing the variable.
## Examples
In the following code, the call to `create_file` may fail and then the call `f.close` will raise a `NoMethodError` since `f` will be `nil` at that point.
```ruby
def dump(x)
f = create_file
f.puts(x)
ensure
f.close
end
```
We can fix this by using safe navigation:
```ruby
def dump(x)
f = create_file
f.puts(x)
ensure
f&.close
end
```
## References
- https://www.rubyguides.com/: [Nil](https://www.rubyguides.com/2018/01/ruby-nil/)
- https://ruby-doc.org/: [NoMethodError](https://ruby-doc.org/core-2.6.5/NoMethodError.html)

View File

@@ -5,20 +5,91 @@
* @kind problem
* @problem.severity error
* @id rb/uninitialized-local-variable
* @tags reliability
* @tags quality
* reliability
* correctness
* @precision low
* @precision high
*/
import codeql.ruby.AST
import codeql.ruby.dataflow.SSA
import codeql.ruby.controlflow.internal.Guards as Guards
import codeql.ruby.controlflow.CfgNodes
import codeql.ruby.ast.internal.Variable
class RelevantLocalVariableReadAccess extends LocalVariableReadAccess {
RelevantLocalVariableReadAccess() {
not exists(MethodCall c |
c.getReceiver() = this and
private predicate isInBooleanContext(AstNode n) {
exists(ConditionalExpr i |
n = i.getCondition()
or
isInBooleanContext(i) and
n = i.getBranch(_)
)
or
n = any(ConditionalLoop parent).getCondition()
or
n = any(InClause parent).getCondition()
or
n = any(LogicalAndExpr op).getAnOperand()
or
n = any(LogicalOrExpr op).getAnOperand()
or
n = any(NotExpr op).getOperand()
or
n = any(StmtSequence parent | isInBooleanContext(parent)).getLastStmt()
or
exists(CaseExpr c, WhenClause w |
not exists(c.getValue()) and
c.getABranch() = w
|
w.getPattern(_) = n
or
w = n
)
}
private predicate isGuarded(LocalVariableReadAccess read) {
exists(AstCfgNode guard, boolean branch |
Guards::guardControlsBlock(guard, read.getAControlFlowNode().getBasicBlock(), branch)
|
// guard is `var`
guard.getAstNode() = read.getVariable().getAnAccess() and
branch = true
or
// guard is `var.nil?`
exists(MethodCall c | guard.getAstNode() = c |
c.getReceiver() = read.getVariable().getAnAccess() and
c.getMethodName() = "nil?"
)
) and
branch = false
)
}
private predicate isNilChecked(LocalVariableReadAccess read) {
exists(MethodCall c | c.getReceiver() = read |
c.getMethodName() = "nil?"
or
c.isSafeNavigation()
)
}
/**
* Holds if `name` is the name of a method defined on `nil`.
* See https://ruby-doc.org/core-2.5.8/NilClass.html
*/
private predicate isNilMethodName(string name) {
name in [
"inspect", "instance_of?", "is_a?", "kind_of?", "method", "nil?", "rationalize", "to_a",
"to_c", "to_f", "to_h", "to_i", "to_r", "to_s"
]
}
class RelevantLocalVariableReadAccess extends LocalVariableReadAccess instanceof TVariableAccessReal
{
RelevantLocalVariableReadAccess() {
not isInBooleanContext(this) and
not isNilChecked(this) and
not isGuarded(this) and
this = any(MethodCall m | not isNilMethodName(m.getMethodName())).getReceiver()
}
}

View File

@@ -0,0 +1,14 @@
def m
puts "m"
end
def foo
m # calls m above
if false
m = "0"
m # reads local variable m
else
end
m.strip # reads uninitialized local variable m, `nil`, and crashes
m2 # undefined local variable or method 'm2' for main (NameError)
end

View File

@@ -0,0 +1,4 @@
| UninitializedLocal.rb:12:3:12:3 | m | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:8:7:8:7 | m | m |
| UninitializedLocal.rb:34:5:34:5 | b | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:27:9:27:9 | b | b |
| UninitializedLocal.rb:34:23:34:23 | b | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:27:9:27:9 | b | b |
| UninitializedLocal.rb:76:5:76:5 | i | Local variable $@ may be used before it is initialized. | UninitializedLocal.rb:73:9:73:9 | i | i |

View File

@@ -0,0 +1,2 @@
query: queries/variables/UninitializedLocal.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,77 @@
def m
puts "m"
end
def foo
m # calls m above
if false
m = "0"
m # reads local variable m
else
end
m.strip #$ Alert
m2 # undefined local variable or method 'm2' for main (NameError)
end
def test_guards
if (a = "3" && a) # OK - a is in a Boolean context
a.strip
end
if (a = "3") && a # OK - a is assigned in the previous conjunct
a.strip
end
if !(a = "3") or a # OK - a is assigned in the previous conjunct
a.strip
end
if false
b = "0"
end
b.nil?
b || 0 # OK
b&.strip # OK - safe navigation
b.strip if b # OK
b.close if b && !b.closed # OK
b.blowup if b || !b.blownup #$ Alert
if false
c = "0"
end
unless c
return
end
c.strip # OK - given above unless
if false
d = "0"
end
if (d.nil?)
return
end
d.strip # OK - given above check
if false
e = "0"
end
unless (!e.nil?)
return
end
e.strip # OK - given above unless
end
def test_loop
begin
if false
a = 0
else
set_a
end
end until a # OK
a.strip # OK - given previous until
end
def test_for
for i in ["foo", "bar"] # OK - since 0..10 cannot raise
puts i.strip
end
i.strip #$ SPURIOUS: Alert
end

View File

@@ -3,5 +3,12 @@ extensions:
pack: codeql/rust-all
extensible: sourceModel
data:
# Alloc
- ["repo:https://github.com/rust-lang/libc:libc", "::free", "Argument[0]", "pointer-invalidate", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["repo:https://github.com/rust-lang/libc:libc", "::malloc", "Argument[0]", "alloc-size", "manual"]
- ["repo:https://github.com/rust-lang/libc:libc", "::aligned_alloc", "Argument[1]", "alloc-size", "manual"]
- ["repo:https://github.com/rust-lang/libc:libc", "::calloc", "Argument[0,1]", "alloc-size", "manual"]
- ["repo:https://github.com/rust-lang/libc:libc", "::realloc", "Argument[1]", "alloc-size", "manual"]

View File

@@ -1,4 +1,30 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sourceModel
data:
# Alloc
- ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
# Alloc
- ["lang:alloc", "crate::alloc::alloc", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "crate::alloc::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "crate::alloc::realloc", "Argument[2]", "alloc-size", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::global::GlobalAlloc>::alloc", "Argument[0]", "alloc-layout", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::global::GlobalAlloc>::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::Allocator>::allocate", "Argument[0]", "alloc-layout", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::Allocator>::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::Allocator>::grow", "Argument[2]", "alloc-layout", "manual"]
- ["lang:std", "<crate::alloc::System as crate::alloc::Allocator>::grow_zeroed", "Argument[2]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::global::GlobalAlloc>::alloc", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::global::GlobalAlloc>::alloc_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::Allocator>::allocate", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::Allocator>::allocate_zeroed", "Argument[0]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::Allocator>::grow", "Argument[2]", "alloc-layout", "manual"]
- ["lang:alloc", "<crate::alloc::Global as crate::alloc::Allocator>::grow_zeroed", "Argument[2]", "alloc-layout", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: summaryModel
@@ -9,9 +35,3 @@ extensions:
- ["lang:alloc", "<crate::string::String>::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["lang:alloc", "<crate::string::String>::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["lang:alloc", "<_ as crate::string::ToString>::to_string", "Argument[self]", "ReturnValue", "taint", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: sourceModel
data:
# Alloc
- ["lang:alloc", "crate::alloc::dealloc", "Argument[0]", "pointer-invalidate", "manual"]

View File

@@ -17,6 +17,21 @@ extensions:
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::collect", "Argument[self].Element", "ReturnValue.Element", "value", "manual"]
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::map", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["lang:core", "<crate::slice::iter::Iter as crate::iter::traits::iterator::Iterator>::for_each", "Argument[self].Element", "Argument[0].Parameter[0]", "value", "manual"]
# Layout
- ["lang:core", "<crate::alloc::layout::Layout>::from_size_align", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::from_size_align_unchecked", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::array", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::repeat", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::repeat", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::repeat_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::repeat_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::extend", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::extend", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::extend_packed", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::extend_packed", "Argument[0]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::align_to", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::pad_to_align", "Argument[self]", "ReturnValue", "taint", "manual"]
- ["lang:core", "<crate::alloc::layout::Layout>::size", "Argument[self]", "ReturnValue", "taint", "manual"]
# Ptr
- ["lang:core", "crate::ptr::read", "Argument[0].Reference", "ReturnValue", "value", "manual"]
- ["lang:core", "crate::ptr::read_unaligned", "Argument[0].Reference", "ReturnValue", "value", "manual"]

View File

@@ -0,0 +1,95 @@
/**
* Provides classes and predicates for reasoning about uncontrolled allocation
* size vulnerabilities.
*/
import rust
private import codeql.rust.Concepts
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSink
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
private import codeql.rust.controlflow.CfgNodes as CfgNodes
/**
* Provides default sources, sinks and barriers for detecting uncontrolled
* allocation size vulnerabilities, as well as extension points for adding your own.
*/
module UncontrolledAllocationSize {
/**
* A data flow sink for uncontrolled allocation size vulnerabilities.
*/
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "UncontrolledAllocationSize" }
}
/**
* A barrier for uncontrolled allocation size vulnerabilities.
*/
abstract class Barrier extends DataFlow::Node { }
/**
* A sink for uncontrolled allocation size from model data.
*/
private class ModelsAsDataSink extends Sink {
ModelsAsDataSink() { sinkNode(this, ["alloc-size", "alloc-layout"]) }
}
/**
* A barrier for uncontrolled allocation size that is an upper bound check / guard.
*/
private class UpperBoundCheckBarrier extends Barrier {
UpperBoundCheckBarrier() {
this = DataFlow::BarrierGuard<isUpperBoundCheck/3>::getABarrierNode()
}
}
/**
* Gets the operand on the "greater" (or "greater-or-equal") side
* of this relational expression, that is, the side that is larger
* if the overall expression evaluates to `true`; for example on
* `x <= 20` this is the `20`, and on `y > 0` it is `y`.
*/
private Expr getGreaterOperand(BinaryExpr op) {
op.getOperatorName() = ["<", "<="] and
result = op.getRhs()
or
op.getOperatorName() = [">", ">="] and
result = op.getLhs()
}
/**
* Gets the operand on the "lesser" (or "lesser-or-equal") side
* of this relational expression, that is, the side that is smaller
* if the overall expression evaluates to `true`; for example on
* `x <= 20` this is `x`, and on `y > 0` it is the `0`.
*/
private Expr getLesserOperand(BinaryExpr op) {
op.getOperatorName() = ["<", "<="] and
result = op.getLhs()
or
op.getOperatorName() = [">", ">="] and
result = op.getRhs()
}
/**
* Holds if comparison `g` having result `branch` indicates an upper bound for the sub-expression
* `node`. For example when the comparison `x < 10` is true, we have an upper bound for `x`.
*/
private predicate isUpperBoundCheck(CfgNodes::AstCfgNode g, Cfg::CfgNode node, boolean branch) {
exists(BinaryExpr cmp | g = cmp.getACfgNode() |
node = getLesserOperand(cmp).getACfgNode() and
branch = true
or
node = getGreaterOperand(cmp).getACfgNode() and
branch = false
or
cmp.getOperatorName() = "==" and
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
branch = true
or
cmp.getOperatorName() = "!=" and
[cmp.getLhs(), cmp.getRhs()].getACfgNode() = node and
branch = false
)
}
}

View File

@@ -0,0 +1,41 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Allocating memory with a size based on user input may allow arbitrary amounts of memory to be
allocated, leading to a crash or a denial-of-service (DoS) attack.</p>
<p>If the user input is multiplied by a constant, such as the size of a type, the result may
overflow. In a build with the <code>--release</code> flag, Rust performs two's complement wrapping,
with the result that less memory than expected may be allocated. This can lead to buffer overflow
incidents.</p>
</overview>
<recommendation>
<p>Implement a guard to limit the amount of memory that is allocated, and reject the request if
the guard is not met. Ensure that any multiplications in the calculation cannot overflow, either
by guarding their inputs, or using a multiplication routine such as <code>checked_mul</code> that
does not wrap around.</p>
</recommendation>
<example>
<p>In the following example, an arbitrary amount of memory is allocated based on user input. In
addition, due to the multiplication operation, the result may overflow if a very large value is
provided. This may lead to less memory being allocated than expected by other parts of the program.</p>
<sample src="UncontrolledAllocationSizeBad.rs" />
<p>In the fixed example, the user input is checked against a maximum value. If the check fails, an
error is returned, and both the multiplication and allocation do not take place.</p>
<sample src="UncontrolledAllocationSizeGood.rs" />
</example>
<references>
<li>The Rust Programming Language: <a href="https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-overflow">Data Types - Integer Overflow</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,45 @@
/**
* @name Uncontrolled allocation size
* @description Allocating memory with a size controlled by an external user can result in
* arbitrary amounts of memory being allocated, leading to a crash or a
* denial-of-service (DoS) attack.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 7.5
* @precision high
* @id rust/uncontrolled-allocation-size
* @tags reliability
* security
* external/cwe/cwe-770
* external/cwe/cwe-789
*/
import rust
import codeql.rust.Concepts
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.dataflow.internal.DataFlowImpl
import codeql.rust.security.UncontrolledAllocationSizeExtensions
/**
* A taint-tracking configuration for uncontrolled allocation size vulnerabilities.
*/
module UncontrolledAllocationConfig implements DataFlow::ConfigSig {
import UncontrolledAllocationSize
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
}
module UncontrolledAllocationFlow = TaintTracking::Global<UncontrolledAllocationConfig>;
import UncontrolledAllocationFlow::PathGraph
from UncontrolledAllocationFlow::PathNode source, UncontrolledAllocationFlow::PathNode sink
where UncontrolledAllocationFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"This allocation size is derived from a $@ and could allocate arbitrary amounts of memory.",
source.getNode(), "user-provided value"

View File

@@ -0,0 +1,11 @@
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
let num_bytes = user_input.parse::<usize>()? * std::mem::size_of::<u64>();
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
unsafe {
let buffer = std::alloc::alloc(layout); // BAD: uncontrolled allocation size
Ok(buffer)
}
}

View File

@@ -0,0 +1,17 @@
const BUFFER_LIMIT: usize = 10 * 1024;
fn allocate_buffer(user_input: String) -> Result<*mut u8, Error> {
let size = user_input.parse::<usize>()?;
if size > BUFFER_LIMIT {
return Err("Size exceeds limit".into());
}
let num_bytes = size * std::mem::size_of::<u64>();
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
unsafe {
let buffer = std::alloc::alloc(layout); // GOOD
Ok(buffer)
}
}

View File

@@ -22,6 +22,7 @@ private import codeql.rust.security.CleartextLoggingExtensions
private import codeql.rust.security.CleartextTransmissionExtensions
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.TaintedPathExtensions
private import codeql.rust.security.UncontrolledAllocationSizeExtensions
private import codeql.rust.security.WeakSensitiveDataHashingExtensions
/**

View File

@@ -20,15 +20,17 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
class Callable = R::Callable;
class NodeExtended extends DataFlow::Node {
Callable getAsExprEnclosingCallable() { result = this.asExpr().getScope() }
Type getType() { any() }
Callable getEnclosingCallable() {
result = this.(Node::Node).getEnclosingCallable().asCfgScope()
}
}
Callable getAsExprEnclosingCallable(NodeExtended node) { result = node.asExpr().getScope() }
Callable getEnclosingCallable(NodeExtended node) {
result = node.(Node::Node).getEnclosingCallable().asCfgScope()
}
Parameter asParameter(NodeExtended node) { result = node.asParameter() }
private predicate relevant(Function api) {
// Only include functions that have a resolved path.
api.hasCrateOrigin() and

View File

@@ -2162,6 +2162,13 @@ storeStep
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)].Reference in lang:core::_::<crate::result::Result>::as_ref | &ref | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Err(0)] in lang:core::_::<crate::result::Result>::as_ref |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::<crate::string::String as crate::str::traits::FromStr>::from_str | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:alloc::_::<crate::string::String as crate::str::traits::FromStr>::from_str |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::align_to | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::align_to |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::array | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::array |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::extend | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::extend |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::extend_packed | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::extend_packed |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::from_size_align | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::from_size_align |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::repeat | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::repeat |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::repeat_packed | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::alloc::layout::Layout>::repeat_packed |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::cell::once::OnceCell>::try_insert | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::cell::once::OnceCell>::try_insert |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::option::Option>::ok_or | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::option::Option>::ok_or |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::option::Option>::ok_or_else | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::option::Option>::ok_or_else |
@@ -2195,6 +2202,8 @@ storeStep
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text_with_charset | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/seanmonstar/reqwest:reqwest::_::<crate::response::Response>::text_with_charset |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in repo:https://github.com/servo/rust-url:url::_::<crate::Url>::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in repo:https://github.com/servo/rust-url:url::_::<crate::Url>::parse |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:alloc::_::<crate::collections::btree::node::NodeRef>::search_tree_for_bifurcation |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::<crate::alloc::layout::Layout>::extend | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::extend |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:core::_::<crate::alloc::layout::Layout>::repeat | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::alloc::layout::Layout>::repeat |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_ms | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_ms |
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)].Field[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_while | tuple.0 | file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout_while |

View File

@@ -2,16 +2,21 @@
| main.rs:6:25:6:30 | &regex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | &regex | This regular expression is constructed from a $@. | main.rs:4:20:4:32 | ...::var | user-provided value |
edges
| main.rs:4:9:4:16 | username | main.rs:5:25:5:44 | MacroExpr | provenance | |
| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:66 |
| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:1641 |
| main.rs:4:20:4:32 | ...::var | main.rs:4:20:4:40 | ...::var(...) [Ok] | provenance | Src:MaD:1 |
| main.rs:4:20:4:40 | ...::var(...) [Ok] | main.rs:4:20:4:66 | ... .unwrap_or(...) | provenance | MaD:3 |
| main.rs:4:20:4:66 | ... .unwrap_or(...) | main.rs:4:9:4:16 | username | provenance | |
| main.rs:5:9:5:13 | regex | main.rs:6:26:6:30 | regex | provenance | |
| main.rs:5:17:5:45 | res | main.rs:5:25:5:44 | { ... } | provenance | |
| main.rs:5:25:5:44 | ...::format(...) | main.rs:5:17:5:45 | res | provenance | |
| main.rs:5:25:5:44 | ...::must_use(...) | main.rs:5:9:5:13 | regex | provenance | |
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:102 |
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:3064 |
| main.rs:5:25:5:44 | MacroExpr | main.rs:5:25:5:44 | ...::format(...) | provenance | MaD:2 |
| main.rs:5:25:5:44 | { ... } | main.rs:5:25:5:44 | ...::must_use(...) | provenance | MaD:4 |
| main.rs:6:26:6:30 | regex | main.rs:6:25:6:30 | &regex | provenance | |
models
| 1 | Source: lang:std; crate::env::var; environment-source; ReturnValue.Field[crate::result::Result::Ok(0)] |
| 2 | Summary: lang:alloc; crate::fmt::format; Argument[0]; ReturnValue; taint |
| 3 | Summary: lang:core; <crate::result::Result>::unwrap_or; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 4 | Summary: lang:core; crate::hint::must_use; Argument[0]; ReturnValue; value |
nodes
| main.rs:4:9:4:16 | username | semmle.label | username |
| main.rs:4:20:4:32 | ...::var | semmle.label | ...::var |

View File

@@ -1,2 +1,4 @@
query: queries/security/CWE-020/RegexInjection.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,503 @@
#select
| main.rs:18:13:18:31 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:18:13:18:31 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:21:13:21:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:21:13:21:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:22:13:22:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:22:13:22:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:23:13:23:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:23:13:23:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:24:13:24:36 | ...::alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:24:13:24:36 | ...::alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:30:13:30:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:30:13:30:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:33:13:33:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:33:13:33:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:37:13:37:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:37:13:37:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:40:13:40:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:40:13:40:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:50:13:50:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:50:13:50:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:51:13:51:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:51:13:51:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:53:13:53:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:53:13:53:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:54:13:54:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:54:13:54:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:59:13:59:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:59:13:59:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:61:13:61:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:61:13:61:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:63:13:63:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:63:13:63:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:64:13:64:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:64:13:64:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:65:13:65:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:65:13:65:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:68:13:68:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:68:13:68:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:88:13:88:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:88:13:88:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:96:17:96:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:96:17:96:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:102:17:102:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:102:17:102:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:103:17:103:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:103:17:103:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:109:17:109:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:109:17:109:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:111:17:111:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:111:17:111:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:146:17:146:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:146:17:146:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:148:17:148:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:148:17:148:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:152:13:152:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:152:13:152:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:155:13:155:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:155:13:155:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:162:17:162:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:162:17:162:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:169:17:169:33 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:169:17:169:33 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:177:13:177:29 | ...::alloc | main.rs:317:13:317:26 | ...::args | main.rs:177:13:177:29 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:193:32:193:36 | alloc | main.rs:317:13:317:26 | ...::args | main.rs:193:32:193:36 | alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:194:32:194:43 | alloc_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:194:32:194:43 | alloc_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:195:32:195:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:195:32:195:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:196:32:196:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:196:32:196:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:197:32:197:39 | allocate | main.rs:317:13:317:26 | ...::args | main.rs:197:32:197:39 | allocate | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:198:32:198:46 | allocate_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:198:32:198:46 | allocate_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:208:40:208:43 | grow | main.rs:317:13:317:26 | ...::args | main.rs:208:40:208:43 | grow | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:210:40:210:50 | grow_zeroed | main.rs:317:13:317:26 | ...::args | main.rs:210:40:210:50 | grow_zeroed | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:219:13:219:24 | ...::malloc | main.rs:317:13:317:26 | ...::args | main.rs:219:13:219:24 | ...::malloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:220:13:220:31 | ...::aligned_alloc | main.rs:317:13:317:26 | ...::args | main.rs:220:13:220:31 | ...::aligned_alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:222:13:222:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:222:13:222:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:223:13:223:24 | ...::calloc | main.rs:317:13:317:26 | ...::args | main.rs:223:13:223:24 | ...::calloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:224:13:224:25 | ...::realloc | main.rs:317:13:317:26 | ...::args | main.rs:224:13:224:25 | ...::realloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:317:13:317:26 | ...::args | user-provided value |
| main.rs:284:22:284:38 | ...::alloc | main.rs:308:25:308:38 | ...::args | main.rs:284:22:284:38 | ...::alloc | This allocation size is derived from a $@ and could allocate arbitrary amounts of memory. | main.rs:308:25:308:38 | ...::args | user-provided value |
edges
| main.rs:12:36:12:43 | ...: usize | main.rs:18:41:18:41 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:18:13:18:31 | ...::realloc | provenance | MaD:5 Sink:MaD:5 |
| main.rs:18:41:18:41 | v | main.rs:20:50:20:50 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:29:60:29:60 | v | provenance | |
| main.rs:18:41:18:41 | v | main.rs:32:60:32:89 | ... * ... | provenance | |
| main.rs:18:41:18:41 | v | main.rs:35:9:35:10 | s6 | provenance | |
| main.rs:20:9:20:10 | l2 | main.rs:21:31:21:32 | l2 | provenance | |
| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | main.rs:20:14:20:63 | ... .unwrap() | provenance | MaD:31 |
| main.rs:20:14:20:63 | ... .unwrap() | main.rs:20:9:20:10 | l2 | provenance | |
| main.rs:20:50:20:50 | v | main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:21:31:21:32 | l2 | main.rs:21:13:21:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:21:31:21:32 | l2 | main.rs:22:31:22:44 | l2.align_to(...) [Ok] | provenance | MaD:17 |
| main.rs:21:31:21:32 | l2 | main.rs:23:31:23:44 | l2.align_to(...) [Ok] | provenance | MaD:17 |
| main.rs:21:31:21:32 | l2 | main.rs:24:38:24:39 | l2 | provenance | |
| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | main.rs:22:31:22:53 | ... .unwrap() | provenance | MaD:31 |
| main.rs:22:31:22:53 | ... .unwrap() | main.rs:22:13:22:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | main.rs:23:31:23:53 | ... .unwrap() | provenance | MaD:31 |
| main.rs:23:31:23:53 | ... .unwrap() | main.rs:23:31:23:68 | ... .pad_to_align() | provenance | MaD:25 |
| main.rs:23:31:23:68 | ... .pad_to_align() | main.rs:23:13:23:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:24:38:24:39 | l2 | main.rs:24:13:24:36 | ...::alloc_zeroed | provenance | MaD:4 Sink:MaD:4 |
| main.rs:29:9:29:10 | l4 | main.rs:30:31:30:32 | l4 | provenance | |
| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | main.rs:29:9:29:10 | l4 | provenance | |
| main.rs:29:60:29:60 | v | main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:30:31:30:32 | l4 | main.rs:30:13:30:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:32:9:32:10 | l5 | main.rs:33:31:33:32 | l5 | provenance | |
| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | main.rs:32:9:32:10 | l5 | provenance | |
| main.rs:32:60:32:89 | ... * ... | main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:33:31:33:32 | l5 | main.rs:33:13:33:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:35:9:35:10 | s6 | main.rs:36:60:36:61 | s6 | provenance | |
| main.rs:36:9:36:10 | l6 | main.rs:37:31:37:32 | l6 | provenance | |
| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | main.rs:36:9:36:10 | l6 | provenance | |
| main.rs:36:60:36:61 | s6 | main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:37:31:37:32 | l6 | main.rs:37:13:37:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:37:31:37:32 | l6 | main.rs:39:60:39:68 | l6.size() | provenance | MaD:28 |
| main.rs:39:9:39:10 | l7 | main.rs:40:31:40:32 | l7 | provenance | |
| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | main.rs:39:9:39:10 | l7 | provenance | |
| main.rs:39:60:39:68 | l6.size() | main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | provenance | MaD:24 |
| main.rs:40:31:40:32 | l7 | main.rs:40:13:40:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:43:44:43:51 | ...: usize | main.rs:50:41:50:41 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:51:41:51:45 | ... + ... | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:53:48:53:48 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:54:48:54:53 | ... * ... | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:58:34:58:34 | v | provenance | |
| main.rs:43:44:43:51 | ...: usize | main.rs:67:46:67:46 | v | provenance | |
| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | provenance | MaD:31 |
| main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | main.rs:50:31:50:53 | ... .0 | provenance | |
| main.rs:50:31:50:53 | ... .0 | main.rs:50:13:50:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:50:41:50:41 | v | main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | provenance | MaD:31 |
| main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | main.rs:51:31:51:57 | ... .0 | provenance | |
| main.rs:51:31:51:57 | ... .0 | main.rs:51:13:51:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:51:41:51:45 | ... + ... | main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | main.rs:53:31:53:58 | ... .unwrap() | provenance | MaD:31 |
| main.rs:53:31:53:58 | ... .unwrap() | main.rs:53:13:53:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:53:48:53:48 | v | main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 |
| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | main.rs:54:31:54:63 | ... .unwrap() | provenance | MaD:31 |
| main.rs:54:31:54:63 | ... .unwrap() | main.rs:54:13:54:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:54:48:54:53 | ... * ... | main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | provenance | MaD:27 |
| main.rs:58:9:58:20 | TuplePat [tuple.0] | main.rs:58:10:58:11 | k1 | provenance | |
| main.rs:58:10:58:11 | k1 | main.rs:59:31:59:32 | k1 | provenance | |
| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | provenance | MaD:30 |
| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | main.rs:58:9:58:20 | TuplePat [tuple.0] | provenance | |
| main.rs:58:34:58:34 | v | main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | provenance | MaD:26 |
| main.rs:59:31:59:32 | k1 | main.rs:59:13:59:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:59:31:59:32 | k1 | main.rs:60:34:60:35 | k1 | provenance | |
| main.rs:59:31:59:32 | k1 | main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | provenance | MaD:20 |
| main.rs:59:31:59:32 | k1 | main.rs:64:48:64:49 | k1 | provenance | |
| main.rs:59:31:59:32 | k1 | main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | provenance | MaD:22 |
| main.rs:60:9:60:20 | TuplePat [tuple.0] | main.rs:60:10:60:11 | k2 | provenance | |
| main.rs:60:10:60:11 | k2 | main.rs:61:31:61:32 | k2 | provenance | |
| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | provenance | MaD:31 |
| main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | main.rs:60:9:60:20 | TuplePat [tuple.0] | provenance | |
| main.rs:60:34:60:35 | k1 | main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | provenance | MaD:19 |
| main.rs:61:31:61:32 | k2 | main.rs:61:13:61:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:62:9:62:20 | TuplePat [tuple.0] | main.rs:62:10:62:11 | k3 | provenance | |
| main.rs:62:10:62:11 | k3 | main.rs:63:31:63:32 | k3 | provenance | |
| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | provenance | MaD:31 |
| main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | main.rs:62:9:62:20 | TuplePat [tuple.0] | provenance | |
| main.rs:63:31:63:32 | k3 | main.rs:63:13:63:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | main.rs:64:31:64:59 | ... .unwrap() | provenance | MaD:31 |
| main.rs:64:31:64:59 | ... .unwrap() | main.rs:64:13:64:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:64:48:64:49 | k1 | main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | provenance | MaD:21 |
| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | main.rs:65:31:65:59 | ... .unwrap() | provenance | MaD:31 |
| main.rs:65:31:65:59 | ... .unwrap() | main.rs:65:13:65:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:67:9:67:10 | l4 | main.rs:68:31:68:32 | l4 | provenance | |
| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | main.rs:67:14:67:56 | ... .unwrap() | provenance | MaD:31 |
| main.rs:67:14:67:56 | ... .unwrap() | main.rs:67:9:67:10 | l4 | provenance | |
| main.rs:67:46:67:46 | v | main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:68:31:68:32 | l4 | main.rs:68:13:68:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:86:35:86:42 | ...: usize | main.rs:87:54:87:54 | v | provenance | |
| main.rs:87:9:87:14 | layout | main.rs:88:31:88:36 | layout | provenance | |
| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | main.rs:87:18:87:67 | ... .unwrap() | provenance | MaD:31 |
| main.rs:87:18:87:67 | ... .unwrap() | main.rs:87:9:87:14 | layout | provenance | |
| main.rs:87:54:87:54 | v | main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:88:31:88:36 | layout | main.rs:88:13:88:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:91:38:91:45 | ...: usize | main.rs:92:47:92:47 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:101:51:101:51 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:105:33:105:33 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:145:51:145:51 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:151:62:151:62 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:154:62:154:62 | v | provenance | |
| main.rs:91:38:91:45 | ...: usize | main.rs:161:55:161:55 | v | provenance | |
| main.rs:92:9:92:10 | l1 | main.rs:96:35:96:36 | l1 | provenance | |
| main.rs:92:9:92:10 | l1 | main.rs:102:35:102:36 | l1 | provenance | |
| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | main.rs:92:14:92:57 | ... .unwrap() | provenance | MaD:31 |
| main.rs:92:14:92:57 | ... .unwrap() | main.rs:92:9:92:10 | l1 | provenance | |
| main.rs:92:47:92:47 | v | main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:96:35:96:36 | l1 | main.rs:96:17:96:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:96:35:96:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
| main.rs:96:35:96:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
| main.rs:101:13:101:14 | l3 | main.rs:103:35:103:36 | l3 | provenance | |
| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | main.rs:101:18:101:61 | ... .unwrap() | provenance | MaD:31 |
| main.rs:101:18:101:61 | ... .unwrap() | main.rs:101:13:101:14 | l3 | provenance | |
| main.rs:101:51:101:51 | v | main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:102:35:102:36 | l1 | main.rs:102:17:102:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:102:35:102:36 | l1 | main.rs:109:35:109:36 | l1 | provenance | |
| main.rs:102:35:102:36 | l1 | main.rs:111:35:111:36 | l1 | provenance | |
| main.rs:103:35:103:36 | l3 | main.rs:103:17:103:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:105:33:105:33 | v | main.rs:86:35:86:42 | ...: usize | provenance | |
| main.rs:109:35:109:36 | l1 | main.rs:109:17:109:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:109:35:109:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
| main.rs:111:35:111:36 | l1 | main.rs:111:17:111:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:111:35:111:36 | l1 | main.rs:146:35:146:36 | l1 | provenance | |
| main.rs:145:13:145:14 | l9 | main.rs:148:35:148:36 | l9 | provenance | |
| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | main.rs:145:18:145:61 | ... .unwrap() | provenance | MaD:31 |
| main.rs:145:18:145:61 | ... .unwrap() | main.rs:145:13:145:14 | l9 | provenance | |
| main.rs:145:51:145:51 | v | main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:146:35:146:36 | l1 | main.rs:146:17:146:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:146:35:146:36 | l1 | main.rs:177:31:177:32 | l1 | provenance | |
| main.rs:148:35:148:36 | l9 | main.rs:148:17:148:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:151:9:151:11 | l10 | main.rs:152:31:152:33 | l10 | provenance | |
| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | main.rs:151:15:151:78 | ... .unwrap() | provenance | MaD:31 |
| main.rs:151:15:151:78 | ... .unwrap() | main.rs:151:9:151:11 | l10 | provenance | |
| main.rs:151:48:151:68 | ...::min(...) | main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:151:62:151:62 | v | main.rs:151:48:151:68 | ...::min(...) | provenance | MaD:34 |
| main.rs:152:31:152:33 | l10 | main.rs:152:13:152:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:154:9:154:11 | l11 | main.rs:155:31:155:33 | l11 | provenance | |
| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | main.rs:154:15:154:78 | ... .unwrap() | provenance | MaD:31 |
| main.rs:154:15:154:78 | ... .unwrap() | main.rs:154:9:154:11 | l11 | provenance | |
| main.rs:154:48:154:68 | ...::max(...) | main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:154:62:154:62 | v | main.rs:154:48:154:68 | ...::max(...) | provenance | MaD:33 |
| main.rs:155:31:155:33 | l11 | main.rs:155:13:155:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:161:13:161:15 | l13 | main.rs:162:35:162:37 | l13 | provenance | |
| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | main.rs:161:19:161:68 | ... .unwrap() | provenance | MaD:31 |
| main.rs:161:19:161:68 | ... .unwrap() | main.rs:161:13:161:15 | l13 | provenance | |
| main.rs:161:55:161:55 | v | main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:162:35:162:37 | l13 | main.rs:162:17:162:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:162:35:162:37 | l13 | main.rs:169:35:169:37 | l13 | provenance | |
| main.rs:169:35:169:37 | l13 | main.rs:169:17:169:33 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:177:31:177:32 | l1 | main.rs:177:13:177:29 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:183:29:183:36 | ...: usize | main.rs:192:46:192:46 | v | provenance | |
| main.rs:192:9:192:10 | l2 | main.rs:193:38:193:39 | l2 | provenance | |
| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | main.rs:192:14:192:56 | ... .unwrap() | provenance | MaD:31 |
| main.rs:192:14:192:56 | ... .unwrap() | main.rs:192:9:192:10 | l2 | provenance | |
| main.rs:192:46:192:46 | v | main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | provenance | MaD:18 |
| main.rs:193:38:193:39 | l2 | main.rs:193:32:193:36 | alloc | provenance | MaD:10 Sink:MaD:10 |
| main.rs:193:38:193:39 | l2 | main.rs:194:45:194:46 | l2 | provenance | |
| main.rs:194:45:194:46 | l2 | main.rs:194:32:194:43 | alloc_zeroed | provenance | MaD:11 Sink:MaD:11 |
| main.rs:194:45:194:46 | l2 | main.rs:195:41:195:42 | l2 | provenance | |
| main.rs:195:41:195:42 | l2 | main.rs:195:32:195:39 | allocate | provenance | MaD:6 Sink:MaD:6 |
| main.rs:195:41:195:42 | l2 | main.rs:196:48:196:49 | l2 | provenance | |
| main.rs:196:48:196:49 | l2 | main.rs:196:32:196:46 | allocate_zeroed | provenance | MaD:7 Sink:MaD:7 |
| main.rs:196:48:196:49 | l2 | main.rs:197:41:197:42 | l2 | provenance | |
| main.rs:197:41:197:42 | l2 | main.rs:197:32:197:39 | allocate | provenance | MaD:1 Sink:MaD:1 |
| main.rs:197:41:197:42 | l2 | main.rs:198:48:198:49 | l2 | provenance | |
| main.rs:198:48:198:49 | l2 | main.rs:198:32:198:46 | allocate_zeroed | provenance | MaD:2 Sink:MaD:2 |
| main.rs:198:48:198:49 | l2 | main.rs:208:53:208:54 | l2 | provenance | |
| main.rs:198:48:198:49 | l2 | main.rs:210:60:210:61 | l2 | provenance | |
| main.rs:208:53:208:54 | l2 | main.rs:208:40:208:43 | grow | provenance | MaD:8 Sink:MaD:8 |
| main.rs:210:60:210:61 | l2 | main.rs:210:40:210:50 | grow_zeroed | provenance | MaD:9 Sink:MaD:9 |
| main.rs:217:27:217:34 | ...: usize | main.rs:219:26:219:26 | v | provenance | |
| main.rs:219:26:219:26 | v | main.rs:219:13:219:24 | ...::malloc | provenance | MaD:14 Sink:MaD:14 |
| main.rs:219:26:219:26 | v | main.rs:220:36:220:36 | v | provenance | |
| main.rs:220:36:220:36 | v | main.rs:220:13:220:31 | ...::aligned_alloc | provenance | MaD:12 Sink:MaD:12 |
| main.rs:220:36:220:36 | v | main.rs:222:30:222:30 | v | provenance | |
| main.rs:222:30:222:30 | v | main.rs:222:13:222:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
| main.rs:222:30:222:30 | v | main.rs:223:26:223:26 | v | provenance | |
| main.rs:223:26:223:26 | v | main.rs:223:13:223:24 | ...::calloc | provenance | MaD:13 Sink:MaD:13 |
| main.rs:223:26:223:26 | v | main.rs:224:31:224:31 | v | provenance | |
| main.rs:224:31:224:31 | v | main.rs:224:13:224:25 | ...::realloc | provenance | MaD:15 Sink:MaD:15 |
| main.rs:279:24:279:41 | ...: String | main.rs:280:21:280:47 | user_input.parse() [Ok] | provenance | MaD:32 |
| main.rs:280:9:280:17 | num_bytes | main.rs:282:54:282:62 | num_bytes | provenance | |
| main.rs:280:21:280:47 | user_input.parse() [Ok] | main.rs:280:21:280:48 | TryExpr | provenance | |
| main.rs:280:21:280:48 | TryExpr | main.rs:280:9:280:17 | num_bytes | provenance | |
| main.rs:282:9:282:14 | layout | main.rs:284:40:284:45 | layout | provenance | |
| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | main.rs:282:18:282:75 | ... .unwrap() | provenance | MaD:31 |
| main.rs:282:18:282:75 | ... .unwrap() | main.rs:282:9:282:14 | layout | provenance | |
| main.rs:282:54:282:62 | num_bytes | main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | provenance | MaD:23 |
| main.rs:284:40:284:45 | layout | main.rs:284:22:284:38 | ...::alloc | provenance | MaD:3 Sink:MaD:3 |
| main.rs:308:25:308:38 | ...::args | main.rs:308:25:308:40 | ...::args(...) [element] | provenance | Src:MaD:16 |
| main.rs:308:25:308:40 | ...::args(...) [element] | main.rs:308:25:308:47 | ... .nth(...) [Some] | provenance | MaD:35 |
| main.rs:308:25:308:47 | ... .nth(...) [Some] | main.rs:308:25:308:74 | ... .unwrap_or(...) | provenance | MaD:29 |
| main.rs:308:25:308:74 | ... .unwrap_or(...) | main.rs:279:24:279:41 | ...: String | provenance | |
| main.rs:317:9:317:9 | v | main.rs:320:34:320:34 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:321:42:321:42 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:322:36:322:36 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:323:27:323:27 | v | provenance | |
| main.rs:317:9:317:9 | v | main.rs:324:25:324:25 | v | provenance | |
| main.rs:317:13:317:26 | ...::args | main.rs:317:13:317:28 | ...::args(...) [element] | provenance | Src:MaD:16 |
| main.rs:317:13:317:28 | ...::args(...) [element] | main.rs:317:13:317:35 | ... .nth(...) [Some] | provenance | MaD:35 |
| main.rs:317:13:317:35 | ... .nth(...) [Some] | main.rs:317:13:317:65 | ... .unwrap_or(...) | provenance | MaD:29 |
| main.rs:317:13:317:65 | ... .unwrap_or(...) | main.rs:317:13:317:82 | ... .parse() [Ok] | provenance | MaD:32 |
| main.rs:317:13:317:82 | ... .parse() [Ok] | main.rs:317:13:317:91 | ... .unwrap() | provenance | MaD:31 |
| main.rs:317:13:317:91 | ... .unwrap() | main.rs:317:9:317:9 | v | provenance | |
| main.rs:320:34:320:34 | v | main.rs:12:36:12:43 | ...: usize | provenance | |
| main.rs:321:42:321:42 | v | main.rs:43:44:43:51 | ...: usize | provenance | |
| main.rs:322:36:322:36 | v | main.rs:91:38:91:45 | ...: usize | provenance | |
| main.rs:323:27:323:27 | v | main.rs:183:29:183:36 | ...: usize | provenance | |
| main.rs:324:25:324:25 | v | main.rs:217:27:217:34 | ...: usize | provenance | |
models
| 1 | Sink: lang:alloc; <crate::alloc::Global as crate::alloc::Allocator>::allocate; alloc-layout; Argument[0] |
| 2 | Sink: lang:alloc; <crate::alloc::Global as crate::alloc::Allocator>::allocate_zeroed; alloc-layout; Argument[0] |
| 3 | Sink: lang:alloc; crate::alloc::alloc; alloc-layout; Argument[0] |
| 4 | Sink: lang:alloc; crate::alloc::alloc_zeroed; alloc-layout; Argument[0] |
| 5 | Sink: lang:alloc; crate::alloc::realloc; alloc-size; Argument[2] |
| 6 | Sink: lang:std; <crate::alloc::System as crate::alloc::Allocator>::allocate; alloc-layout; Argument[0] |
| 7 | Sink: lang:std; <crate::alloc::System as crate::alloc::Allocator>::allocate_zeroed; alloc-layout; Argument[0] |
| 8 | Sink: lang:std; <crate::alloc::System as crate::alloc::Allocator>::grow; alloc-layout; Argument[2] |
| 9 | Sink: lang:std; <crate::alloc::System as crate::alloc::Allocator>::grow_zeroed; alloc-layout; Argument[2] |
| 10 | Sink: lang:std; <crate::alloc::System as crate::alloc::global::GlobalAlloc>::alloc; alloc-layout; Argument[0] |
| 11 | Sink: lang:std; <crate::alloc::System as crate::alloc::global::GlobalAlloc>::alloc_zeroed; alloc-layout; Argument[0] |
| 12 | Sink: repo:https://github.com/rust-lang/libc:libc; ::aligned_alloc; alloc-size; Argument[1] |
| 13 | Sink: repo:https://github.com/rust-lang/libc:libc; ::calloc; alloc-size; Argument[0,1] |
| 14 | Sink: repo:https://github.com/rust-lang/libc:libc; ::malloc; alloc-size; Argument[0] |
| 15 | Sink: repo:https://github.com/rust-lang/libc:libc; ::realloc; alloc-size; Argument[1] |
| 16 | Source: lang:std; crate::env::args; command-line-source; ReturnValue.Element |
| 17 | Summary: lang:core; <crate::alloc::layout::Layout>::align_to; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 18 | Summary: lang:core; <crate::alloc::layout::Layout>::array; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 19 | Summary: lang:core; <crate::alloc::layout::Layout>::extend; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
| 20 | Summary: lang:core; <crate::alloc::layout::Layout>::extend; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
| 21 | Summary: lang:core; <crate::alloc::layout::Layout>::extend_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 22 | Summary: lang:core; <crate::alloc::layout::Layout>::extend_packed; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 23 | Summary: lang:core; <crate::alloc::layout::Layout>::from_size_align; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 24 | Summary: lang:core; <crate::alloc::layout::Layout>::from_size_align_unchecked; Argument[0]; ReturnValue; taint |
| 25 | Summary: lang:core; <crate::alloc::layout::Layout>::pad_to_align; Argument[self]; ReturnValue; taint |
| 26 | Summary: lang:core; <crate::alloc::layout::Layout>::repeat; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)].Field[0]; taint |
| 27 | Summary: lang:core; <crate::alloc::layout::Layout>::repeat_packed; Argument[0]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 28 | Summary: lang:core; <crate::alloc::layout::Layout>::size; Argument[self]; ReturnValue; taint |
| 29 | Summary: lang:core; <crate::option::Option>::unwrap_or; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value |
| 30 | Summary: lang:core; <crate::result::Result>::expect; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 31 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
| 32 | Summary: lang:core; <str>::parse; Argument[self]; ReturnValue.Field[crate::result::Result::Ok(0)]; taint |
| 33 | Summary: lang:core; crate::cmp::max; Argument[0]; ReturnValue; value |
| 34 | Summary: lang:core; crate::cmp::min; Argument[0]; ReturnValue; value |
| 35 | Summary: lang:core; crate::iter::traits::iterator::Iterator::nth; Argument[self].Element; ReturnValue.Field[crate::option::Option::Some(0)]; value |
nodes
| main.rs:12:36:12:43 | ...: usize | semmle.label | ...: usize |
| main.rs:18:13:18:31 | ...::realloc | semmle.label | ...::realloc |
| main.rs:18:41:18:41 | v | semmle.label | v |
| main.rs:20:9:20:10 | l2 | semmle.label | l2 |
| main.rs:20:14:20:54 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
| main.rs:20:14:20:63 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:20:50:20:50 | v | semmle.label | v |
| main.rs:21:13:21:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:21:31:21:32 | l2 | semmle.label | l2 |
| main.rs:22:13:22:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:22:31:22:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] |
| main.rs:22:31:22:53 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:23:13:23:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:23:31:23:44 | l2.align_to(...) [Ok] | semmle.label | l2.align_to(...) [Ok] |
| main.rs:23:31:23:53 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:23:31:23:68 | ... .pad_to_align() | semmle.label | ... .pad_to_align() |
| main.rs:24:13:24:36 | ...::alloc_zeroed | semmle.label | ...::alloc_zeroed |
| main.rs:24:38:24:39 | l2 | semmle.label | l2 |
| main.rs:29:9:29:10 | l4 | semmle.label | l4 |
| main.rs:29:14:29:64 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
| main.rs:29:60:29:60 | v | semmle.label | v |
| main.rs:30:13:30:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:30:31:30:32 | l4 | semmle.label | l4 |
| main.rs:32:9:32:10 | l5 | semmle.label | l5 |
| main.rs:32:14:32:118 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
| main.rs:32:60:32:89 | ... * ... | semmle.label | ... * ... |
| main.rs:33:13:33:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:33:31:33:32 | l5 | semmle.label | l5 |
| main.rs:35:9:35:10 | s6 | semmle.label | s6 |
| main.rs:36:9:36:10 | l6 | semmle.label | l6 |
| main.rs:36:14:36:65 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
| main.rs:36:60:36:61 | s6 | semmle.label | s6 |
| main.rs:37:13:37:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:37:31:37:32 | l6 | semmle.label | l6 |
| main.rs:39:9:39:10 | l7 | semmle.label | l7 |
| main.rs:39:14:39:72 | ...::from_size_align_unchecked(...) | semmle.label | ...::from_size_align_unchecked(...) |
| main.rs:39:60:39:68 | l6.size() | semmle.label | l6.size() |
| main.rs:40:13:40:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:40:31:40:32 | l7 | semmle.label | l7 |
| main.rs:43:44:43:51 | ...: usize | semmle.label | ...: usize |
| main.rs:50:13:50:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:50:31:50:42 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] |
| main.rs:50:31:50:51 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] |
| main.rs:50:31:50:53 | ... .0 | semmle.label | ... .0 |
| main.rs:50:41:50:41 | v | semmle.label | v |
| main.rs:51:13:51:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:51:31:51:46 | l2.repeat(...) [Ok, tuple.0] | semmle.label | l2.repeat(...) [Ok, tuple.0] |
| main.rs:51:31:51:55 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] |
| main.rs:51:31:51:57 | ... .0 | semmle.label | ... .0 |
| main.rs:51:41:51:45 | ... + ... | semmle.label | ... + ... |
| main.rs:53:13:53:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:53:31:53:49 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] |
| main.rs:53:31:53:58 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:53:48:53:48 | v | semmle.label | v |
| main.rs:54:13:54:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:54:31:54:54 | l2.repeat_packed(...) [Ok] | semmle.label | l2.repeat_packed(...) [Ok] |
| main.rs:54:31:54:63 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:54:48:54:53 | ... * ... | semmle.label | ... * ... |
| main.rs:58:9:58:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
| main.rs:58:10:58:11 | k1 | semmle.label | k1 |
| main.rs:58:24:58:35 | l3.repeat(...) [Ok, tuple.0] | semmle.label | l3.repeat(...) [Ok, tuple.0] |
| main.rs:58:24:58:66 | ... .expect(...) [tuple.0] | semmle.label | ... .expect(...) [tuple.0] |
| main.rs:58:34:58:34 | v | semmle.label | v |
| main.rs:59:13:59:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:59:31:59:32 | k1 | semmle.label | k1 |
| main.rs:60:9:60:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
| main.rs:60:10:60:11 | k2 | semmle.label | k2 |
| main.rs:60:24:60:36 | l3.extend(...) [Ok, tuple.0] | semmle.label | l3.extend(...) [Ok, tuple.0] |
| main.rs:60:24:60:45 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] |
| main.rs:60:34:60:35 | k1 | semmle.label | k1 |
| main.rs:61:13:61:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:61:31:61:32 | k2 | semmle.label | k2 |
| main.rs:62:9:62:20 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
| main.rs:62:10:62:11 | k3 | semmle.label | k3 |
| main.rs:62:24:62:36 | k1.extend(...) [Ok, tuple.0] | semmle.label | k1.extend(...) [Ok, tuple.0] |
| main.rs:62:24:62:45 | ... .unwrap() [tuple.0] | semmle.label | ... .unwrap() [tuple.0] |
| main.rs:63:13:63:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:63:31:63:32 | k3 | semmle.label | k3 |
| main.rs:64:13:64:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:64:31:64:50 | l3.extend_packed(...) [Ok] | semmle.label | l3.extend_packed(...) [Ok] |
| main.rs:64:31:64:59 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:64:48:64:49 | k1 | semmle.label | k1 |
| main.rs:65:13:65:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:65:31:65:50 | k1.extend_packed(...) [Ok] | semmle.label | k1.extend_packed(...) [Ok] |
| main.rs:65:31:65:59 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:67:9:67:10 | l4 | semmle.label | l4 |
| main.rs:67:14:67:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:67:14:67:56 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:67:46:67:46 | v | semmle.label | v |
| main.rs:68:13:68:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:68:31:68:32 | l4 | semmle.label | l4 |
| main.rs:86:35:86:42 | ...: usize | semmle.label | ...: usize |
| main.rs:87:9:87:14 | layout | semmle.label | layout |
| main.rs:87:18:87:58 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
| main.rs:87:18:87:67 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:87:54:87:54 | v | semmle.label | v |
| main.rs:88:13:88:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:88:31:88:36 | layout | semmle.label | layout |
| main.rs:91:38:91:45 | ...: usize | semmle.label | ...: usize |
| main.rs:92:9:92:10 | l1 | semmle.label | l1 |
| main.rs:92:14:92:48 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:92:14:92:57 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:92:47:92:47 | v | semmle.label | v |
| main.rs:96:17:96:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:96:35:96:36 | l1 | semmle.label | l1 |
| main.rs:101:13:101:14 | l3 | semmle.label | l3 |
| main.rs:101:18:101:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:101:18:101:61 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:101:51:101:51 | v | semmle.label | v |
| main.rs:102:17:102:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:102:35:102:36 | l1 | semmle.label | l1 |
| main.rs:103:17:103:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:103:35:103:36 | l3 | semmle.label | l3 |
| main.rs:105:33:105:33 | v | semmle.label | v |
| main.rs:109:17:109:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:109:35:109:36 | l1 | semmle.label | l1 |
| main.rs:111:17:111:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:111:35:111:36 | l1 | semmle.label | l1 |
| main.rs:145:13:145:14 | l9 | semmle.label | l9 |
| main.rs:145:18:145:52 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:145:18:145:61 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:145:51:145:51 | v | semmle.label | v |
| main.rs:146:17:146:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:146:35:146:36 | l1 | semmle.label | l1 |
| main.rs:148:17:148:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:148:35:148:36 | l9 | semmle.label | l9 |
| main.rs:151:9:151:11 | l10 | semmle.label | l10 |
| main.rs:151:15:151:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:151:15:151:78 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:151:48:151:68 | ...::min(...) | semmle.label | ...::min(...) |
| main.rs:151:62:151:62 | v | semmle.label | v |
| main.rs:152:13:152:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:152:31:152:33 | l10 | semmle.label | l10 |
| main.rs:154:9:154:11 | l11 | semmle.label | l11 |
| main.rs:154:15:154:69 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:154:15:154:78 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:154:48:154:68 | ...::max(...) | semmle.label | ...::max(...) |
| main.rs:154:62:154:62 | v | semmle.label | v |
| main.rs:155:13:155:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:155:31:155:33 | l11 | semmle.label | l11 |
| main.rs:161:13:161:15 | l13 | semmle.label | l13 |
| main.rs:161:19:161:59 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
| main.rs:161:19:161:68 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:161:55:161:55 | v | semmle.label | v |
| main.rs:162:17:162:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:162:35:162:37 | l13 | semmle.label | l13 |
| main.rs:169:17:169:33 | ...::alloc | semmle.label | ...::alloc |
| main.rs:169:35:169:37 | l13 | semmle.label | l13 |
| main.rs:177:13:177:29 | ...::alloc | semmle.label | ...::alloc |
| main.rs:177:31:177:32 | l1 | semmle.label | l1 |
| main.rs:183:29:183:36 | ...: usize | semmle.label | ...: usize |
| main.rs:192:9:192:10 | l2 | semmle.label | l2 |
| main.rs:192:14:192:47 | ...::array::<...>(...) [Ok] | semmle.label | ...::array::<...>(...) [Ok] |
| main.rs:192:14:192:56 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:192:46:192:46 | v | semmle.label | v |
| main.rs:193:32:193:36 | alloc | semmle.label | alloc |
| main.rs:193:38:193:39 | l2 | semmle.label | l2 |
| main.rs:194:32:194:43 | alloc_zeroed | semmle.label | alloc_zeroed |
| main.rs:194:45:194:46 | l2 | semmle.label | l2 |
| main.rs:195:32:195:39 | allocate | semmle.label | allocate |
| main.rs:195:41:195:42 | l2 | semmle.label | l2 |
| main.rs:196:32:196:46 | allocate_zeroed | semmle.label | allocate_zeroed |
| main.rs:196:48:196:49 | l2 | semmle.label | l2 |
| main.rs:197:32:197:39 | allocate | semmle.label | allocate |
| main.rs:197:41:197:42 | l2 | semmle.label | l2 |
| main.rs:198:32:198:46 | allocate_zeroed | semmle.label | allocate_zeroed |
| main.rs:198:48:198:49 | l2 | semmle.label | l2 |
| main.rs:208:40:208:43 | grow | semmle.label | grow |
| main.rs:208:53:208:54 | l2 | semmle.label | l2 |
| main.rs:210:40:210:50 | grow_zeroed | semmle.label | grow_zeroed |
| main.rs:210:60:210:61 | l2 | semmle.label | l2 |
| main.rs:217:27:217:34 | ...: usize | semmle.label | ...: usize |
| main.rs:219:13:219:24 | ...::malloc | semmle.label | ...::malloc |
| main.rs:219:26:219:26 | v | semmle.label | v |
| main.rs:220:13:220:31 | ...::aligned_alloc | semmle.label | ...::aligned_alloc |
| main.rs:220:36:220:36 | v | semmle.label | v |
| main.rs:222:13:222:24 | ...::calloc | semmle.label | ...::calloc |
| main.rs:222:30:222:30 | v | semmle.label | v |
| main.rs:223:13:223:24 | ...::calloc | semmle.label | ...::calloc |
| main.rs:223:26:223:26 | v | semmle.label | v |
| main.rs:224:13:224:25 | ...::realloc | semmle.label | ...::realloc |
| main.rs:224:31:224:31 | v | semmle.label | v |
| main.rs:279:24:279:41 | ...: String | semmle.label | ...: String |
| main.rs:280:9:280:17 | num_bytes | semmle.label | num_bytes |
| main.rs:280:21:280:47 | user_input.parse() [Ok] | semmle.label | user_input.parse() [Ok] |
| main.rs:280:21:280:48 | TryExpr | semmle.label | TryExpr |
| main.rs:282:9:282:14 | layout | semmle.label | layout |
| main.rs:282:18:282:66 | ...::from_size_align(...) [Ok] | semmle.label | ...::from_size_align(...) [Ok] |
| main.rs:282:18:282:75 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:282:54:282:62 | num_bytes | semmle.label | num_bytes |
| main.rs:284:22:284:38 | ...::alloc | semmle.label | ...::alloc |
| main.rs:284:40:284:45 | layout | semmle.label | layout |
| main.rs:308:25:308:38 | ...::args | semmle.label | ...::args |
| main.rs:308:25:308:40 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
| main.rs:308:25:308:47 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
| main.rs:308:25:308:74 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
| main.rs:317:9:317:9 | v | semmle.label | v |
| main.rs:317:13:317:26 | ...::args | semmle.label | ...::args |
| main.rs:317:13:317:28 | ...::args(...) [element] | semmle.label | ...::args(...) [element] |
| main.rs:317:13:317:35 | ... .nth(...) [Some] | semmle.label | ... .nth(...) [Some] |
| main.rs:317:13:317:65 | ... .unwrap_or(...) | semmle.label | ... .unwrap_or(...) |
| main.rs:317:13:317:82 | ... .parse() [Ok] | semmle.label | ... .parse() [Ok] |
| main.rs:317:13:317:91 | ... .unwrap() | semmle.label | ... .unwrap() |
| main.rs:320:34:320:34 | v | semmle.label | v |
| main.rs:321:42:321:42 | v | semmle.label | v |
| main.rs:322:36:322:36 | v | semmle.label | v |
| main.rs:323:27:323:27 | v | semmle.label | v |
| main.rs:324:25:324:25 | v | semmle.label | v |
subpaths

View File

@@ -0,0 +1,4 @@
query: queries/security/CWE-770/UncontrolledAllocationSize.ql
postprocess:
- utils/test/InlineExpectationsTestQuery.ql
- utils/test/PrettyPrintModels.ql

View File

@@ -0,0 +1,330 @@
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(try_with_capacity)]
#![feature(box_vec_non_null)]
#![feature(non_null_from_ref)]
struct MyStruct {
_a: usize,
_b: i64,
}
unsafe fn test_std_alloc_from_size(v: usize) {
let l1 = std::alloc::Layout::from_size_align(16, 1).unwrap();
let m1 = std::alloc::alloc(l1);
let _ = std::alloc::alloc(l1.align_to(8).unwrap());
let _ = std::alloc::alloc(l1.align_to(8).unwrap().pad_to_align());
let _ = std::alloc::alloc_zeroed(l1);
let _ = std::alloc::realloc(m1, l1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l2 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.align_to(8).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.align_to(8).unwrap().pad_to_align()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::from_size_align(1, v).unwrap(); // not obviously dangerous?
let _ = std::alloc::alloc(l3);
let l4 = std::alloc::Layout::from_size_align_unchecked(v, 1);
let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l5 = std::alloc::Layout::from_size_align_unchecked(v * std::mem::size_of::<i64>(), std::mem::size_of::<i64>());
let _ = std::alloc::alloc(l5); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let s6 = (std::mem::size_of::<MyStruct>() * v) + 1;
let l6 = std::alloc::Layout::from_size_align_unchecked(s6, 4);
let _ = std::alloc::alloc(l6); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l7 = std::alloc::Layout::from_size_align_unchecked(l6.size(), 8);
let _ = std::alloc::alloc(l7); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_std_alloc_new_repeat_extend(v: usize) {
let l1 = std::alloc::Layout::new::<[u8; 10]>();
let _ = std::alloc::alloc(l1);
let l2 = std::alloc::Layout::new::<MyStruct>();
let _ = std::alloc::alloc(l2);
let _ = std::alloc::alloc(l2.repeat(10).unwrap().0);
let _ = std::alloc::alloc(l2.repeat(v).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.repeat(v + 1).unwrap().0); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.repeat_packed(10).unwrap());
let _ = std::alloc::alloc(l2.repeat_packed(v).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2.repeat_packed(v * 10).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::array::<u8>(10).unwrap();
let _ = std::alloc::alloc(l3);
let (k1, _offs1) = l3.repeat(v).expect("arithmetic overflow?");
let _ = std::alloc::alloc(k1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let (k2, _offs2) = l3.extend(k1).unwrap();
let _ = std::alloc::alloc(k2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let (k3, _offs3) = k1.extend(l3).unwrap();
let _ = std::alloc::alloc(k3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l3.extend_packed(k1).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(k1.extend_packed(l3).unwrap()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l4 = std::alloc::Layout::array::<u8>(v).unwrap();
let _ = std::alloc::alloc(l4); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
fn clamp<T: std::cmp::PartialOrd>(v: T, min: T, max: T) -> T {
if v < min {
return min;
} else if v > max {
return max;
} else {
return v;
}
}
unsafe fn test_fn_alloc_bounded(v: usize) {
let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(layout); // $ GOOD (bounded)
}
unsafe fn test_fn_alloc_unbounded(v: usize) {
let layout = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_std_alloc_with_bounds(v: usize, limit: usize) {
let l1 = std::alloc::Layout::array::<u32>(v).unwrap();
if v < 100 {
let l2 = std::alloc::Layout::array::<u32>(v).unwrap();
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l2); // $ GOOD (bounded)
test_fn_alloc_bounded(v);
} else {
let l3 = std::alloc::Layout::array::<u32>(v).unwrap();
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l3); // $ Alert[rust/uncontrolled-allocation-size]=arg1
test_fn_alloc_unbounded(v);
}
if v == 100 {
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
} else {
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
if (v < limit) {
let l4 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l4); // $ GOOD (bounded)
}
if (v < 2 * v) { // not a good bound
let l5 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l5); // $ MISSING: Alert[rust/uncontrolled-allocation-size]=arg1
}
if (true && v < limit && true) {
let l6 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l6); // $ GOOD (bounded)
}
let mut l7;
if (v < 100) {
l7 = std::alloc::Layout::from_size_align(v, 1).unwrap();
} else {
l7 = std::alloc::Layout::from_size_align(100, 1).unwrap();
}
let _ = std::alloc::alloc(l7); // $ GOOD (bounded)
{
let mut v_mut = v;
if v_mut > 100 {
v_mut = 100;
}
let l8 = std::alloc::Layout::array::<u32>(v_mut).unwrap();
let l9 = std::alloc::Layout::array::<u32>(v).unwrap();
let _ = std::alloc::alloc(l1); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l8); // $ GOOD (bounded)
let _ = std::alloc::alloc(l9); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
let l10 = std::alloc::Layout::array::<u32>(std::cmp::min(v, 100)).unwrap();
let _ = std::alloc::alloc(l10); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let l11 = std::alloc::Layout::array::<u32>(std::cmp::max(v, 100)).unwrap();
let _ = std::alloc::alloc(l11); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l12 = std::alloc::Layout::array::<u32>(clamp(v, 1, 100)).unwrap();
let _ = std::alloc::alloc(l12); // $ GOOD (bounded)
for i in 0..10 {
let l13 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l13); // $ Alert[rust/uncontrolled-allocation-size]=arg1
if (v > 1000) {
continue;
}
let l14 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l13); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l14); // $ GOOD (bounded)
}
if v > 100 {
return;
}
let l15 = std::alloc::Layout::from_size_align(v, 1).unwrap();
let _ = std::alloc::alloc(l1); // $ SPURIOUS: Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::alloc(l15); // $ GOOD (bounded)
}
use std::alloc::{GlobalAlloc, Allocator};
unsafe fn test_system_alloc(v: usize) {
let l1 = std::alloc::Layout::array::<u8>(10).unwrap();
let _ = std::alloc::System.alloc(l1);
let _ = std::alloc::System.alloc_zeroed(l1);
let _ = std::alloc::System.allocate(l1).unwrap();
let _ = std::alloc::System.allocate_zeroed(l1).unwrap();
let _ = std::alloc::Global.allocate(l1).unwrap();
let _ = std::alloc::Global.allocate_zeroed(l1).unwrap();
let l2 = std::alloc::Layout::array::<u8>(v).unwrap();
let _ = std::alloc::System.alloc(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::System.alloc_zeroed(l2); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::System.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::System.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::Global.allocate(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = std::alloc::Global.allocate_zeroed(l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let l3 = std::alloc::Layout::array::<u8>(10).unwrap();
let m3 = std::alloc::System.alloc(l3);
let _ = std::alloc::System.realloc(m3, l3, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let l4 = std::alloc::Layout::array::<u8>(10).unwrap();
let m4 = std::ptr::NonNull::<u8>::new(std::alloc::alloc(l4)).unwrap();
if v > 10 {
if v % 2 == 0 {
let _ = std::alloc::System.grow(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
} else {
let _ = std::alloc::System.grow_zeroed(m4, l4, l2).unwrap(); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
} else {
let _ = std::alloc::System.shrink(m4, l4, l2).unwrap();
}
}
unsafe fn test_libc_alloc(v: usize) {
let m1 = libc::malloc(256);
let _ = libc::malloc(v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = libc::aligned_alloc(8, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = libc::aligned_alloc(v, 8);
let _ = libc::calloc(64, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = libc::calloc(v, std::mem::size_of::<i64>()); // $ Alert[rust/uncontrolled-allocation-size]=arg1
let _ = libc::realloc(m1, v); // $ Alert[rust/uncontrolled-allocation-size]=arg1
}
unsafe fn test_vectors(v: usize) {
let _ = Vec::<u64>::try_with_capacity(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = Vec::<u64>::with_capacity(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = Vec::<u64>::try_with_capacity_in(v, std::alloc::Global).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = Vec::<u64>::with_capacity_in(v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let mut v1 = Vec::<u64>::with_capacity(100);
v1.reserve(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
v1.reserve_exact(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = v1.try_reserve(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let _ = v1.try_reserve_exact(v).unwrap(); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
v1.resize(v, 1); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
v1.set_len(v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let l2 = std::alloc::Layout::new::<[u64; 200]>();
let m2 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
let _ = Vec::<u64>::from_parts(m2, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let m3 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
let _ = Vec::<u64>::from_parts(m3, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let m4 = std::ptr::NonNull::<u64>::new(std::alloc::alloc(l2).cast::<u64>()).unwrap();
let _ = Vec::<u64>::from_parts_in(m4, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let m5 = std::alloc::alloc(l2).cast::<u64>();
let _ = Vec::<u64>::from_raw_parts(m5, v, 200); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let m6 = std::alloc::alloc(l2).cast::<u64>();
let _ = Vec::<u64>::from_raw_parts(m6, 100, v); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
let m7 = std::alloc::alloc(l2).cast::<u64>();
let _ = Vec::<u64>::from_raw_parts_in(m7, 100, v, std::alloc::Global); // $ MISSING: Alert[rust/uncontrolled-allocation-size]
}
// --- examples from the qhelp ---
struct Error {
msg: String,
}
impl From<std::num::ParseIntError> for Error {
fn from(err: std::num::ParseIntError) -> Self {
Error { msg: "ParseIntError".to_string() }
}
}
impl From<&str> for Error {
fn from(msg: &str) -> Self {
Error { msg: msg.to_string() }
}
}
fn allocate_buffer_bad(user_input: String) -> Result<*mut u8, Error> {
let num_bytes = user_input.parse::<usize>()? * std::mem::size_of::<u64>();
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
unsafe {
let buffer = std::alloc::alloc(layout); // $ Alert[rust/uncontrolled-allocation-size]=example1
Ok(buffer)
}
}
const BUFFER_LIMIT: usize = 10 * 1024;
fn allocate_buffer_good(user_input: String) -> Result<*mut u8, Error> {
let size = user_input.parse::<usize>()?;
if size > BUFFER_LIMIT {
return Err("Size exceeds limit".into());
}
let num_bytes = size * std::mem::size_of::<u64>();
let layout = std::alloc::Layout::from_size_align(num_bytes, 1).unwrap();
unsafe {
let buffer = std::alloc::alloc(layout); // $ GOOD (bounded)
Ok(buffer)
}
}
fn test_examples() {
allocate_buffer_bad(std::env::args().nth(1).unwrap_or("0".to_string())); // $ Source=example1
allocate_buffer_good(std::env::args().nth(1).unwrap_or("0".to_string()));
}
// --- main ---
fn main() {
println!("--- begin ---");
let v = std::env::args().nth(1).unwrap_or("1024".to_string()).parse::<usize>().unwrap(); // $ Source=arg1
unsafe {
test_std_alloc_from_size(v);
test_std_alloc_new_repeat_extend(v);
test_std_alloc_with_bounds(v, 1000);
test_system_alloc(v);
test_libc_alloc(v);
test_vectors(v);
test_examples();
}
println!("--- end ---");
}

View File

@@ -0,0 +1,3 @@
qltest_cargo_check: true
qltest_dependencies:
- libc = { version = "0.2.11" }

View File

@@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View File

@@ -44,23 +44,19 @@ signature module ModelGeneratorInputSig<LocationSig Location, InputSig<Location>
* Gets the type of this node.
*/
Type getType();
/**
* Gets the enclosing callable of this node.
*/
Callable getEnclosingCallable();
/**
* Gets the enclosing callable of this node, when considered as an expression.
*/
Callable getAsExprEnclosingCallable();
/**
* Gets the parameter corresponding to this node, if any.
*/
Parameter asParameter();
}
/** Gets the enclosing callable of `node`. */
Callable getEnclosingCallable(NodeExtended node);
/**
* Gets the enclosing callable of `node`, when considered as an expression.
*/
Callable getAsExprEnclosingCallable(NodeExtended node);
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter(NodeExtended n);
/**
* A class of callables that are potentially relevant for generating summary or
* neutral models.
@@ -226,6 +222,14 @@ signature module ModelGeneratorInputSig<LocationSig Location, InputSig<Location>
*/
default Lang::ParameterPosition getReturnKindParamPosition(Lang::ReturnKind node) { none() }
/**
* Gets the string that represents the return value corresponding to the
* return kind `kind`.
*
* For most languages this will be the string "ReturnValue".
*/
default string getReturnValueString(Lang::ReturnKind kind) { result = "ReturnValue" }
/**
* Holds if it is irrelevant to generate models for `api` based on data flow analysis.
*
@@ -321,9 +325,11 @@ module MakeModelGenerator<
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
string getOutput(ReturnNodeExt node) {
node.getKind() instanceof DataFlow::ValueReturnKind and
not exists(node.getPosition()) and
result = "ReturnValue"
exists(DataFlow::ValueReturnKind valueReturnKind |
valueReturnKind = node.getKind() and
not exists(node.getPosition()) and
result = getReturnValueString(valueReturnKind.getKind())
)
or
exists(DataFlow::ParameterPosition pos |
pos = node.getPosition() and
@@ -390,7 +396,7 @@ module MakeModelGenerator<
* Gets the MaD string representation of the parameter node `p`.
*/
string parameterNodeAsInput(DataFlow::ParameterNode p) {
result = parameterAccess(p.(NodeExtended).asParameter())
result = parameterAccess(asParameter(p))
or
result = qualifierString() and p instanceof InstanceParameterNode
}
@@ -465,7 +471,7 @@ module MakeModelGenerator<
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof DataFlow::ParameterNode and
exists(Callable c |
c = source.(NodeExtended).getEnclosingCallable() and
c = getEnclosingCallable(source) and
c instanceof DataFlowSummaryTargetApi and
not isUninterestingForHeuristicDataFlowModels(c)
) and
@@ -475,7 +481,7 @@ module MakeModelGenerator<
predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof ReturnNodeExt and
not isOwnInstanceAccessNode(sink) and
not exists(captureQualifierFlow(sink.(NodeExtended).getAsExprEnclosingCallable())) and
not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink))) and
(state instanceof TaintRead or state instanceof TaintStore)
}
@@ -519,8 +525,8 @@ module MakeModelGenerator<
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
) {
exists(string input, string output |
p.(NodeExtended).getEnclosingCallable() = api and
returnNodeExt.getEnclosingCallable() = api and
getEnclosingCallable(p) = api and
getEnclosingCallable(returnNodeExt) = api and
input = parameterNodeAsInput(p) and
output = getOutput(returnNodeExt) and
input != output and
@@ -570,11 +576,12 @@ module MakeModelGenerator<
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof DataFlow::ParameterNode and
source.(NodeExtended).getEnclosingCallable() instanceof DataFlowSummaryTargetApi
getEnclosingCallable(source) instanceof DataFlowSummaryTargetApi
}
predicate isSink(DataFlow::Node sink) {
sink.(ReturnNodeExt).getEnclosingCallable() instanceof DataFlowSummaryTargetApi
sink instanceof ReturnNodeExt and
getEnclosingCallable(sink) instanceof DataFlowSummaryTargetApi
}
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
@@ -613,7 +620,7 @@ module MakeModelGenerator<
* when used in content flow.
*/
private string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
result = parameterContentAccess(p.(NodeExtended).asParameter())
result = parameterContentAccess(asParameter(p))
or
result = qualifierString() and p instanceof InstanceParameterNode
}
@@ -667,8 +674,8 @@ module MakeModelGenerator<
PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
returnNodeExt.getEnclosingCallable() = api and
p.(NodeExtended).getEnclosingCallable() = api
getEnclosingCallable(returnNodeExt) = api and
getEnclosingCallable(p) = api
}
/**
@@ -687,7 +694,7 @@ module MakeModelGenerator<
private DataFlow::ParameterNode parameter;
ContentDataFlowSummaryTargetApi() {
count(string input, string output |
strictcount(string input, string output |
exists(
PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt,
PropagateContentFlow::AccessPath stores
@@ -712,8 +719,8 @@ module MakeModelGenerator<
PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
returnNodeExt.getEnclosingCallable() = api and
p.(NodeExtended).getEnclosingCallable() = api and
getEnclosingCallable(returnNodeExt) = api and
getEnclosingCallable(p) = api and
p = api.getARelevantParameterNode()
}
@@ -985,7 +992,8 @@ module MakeModelGenerator<
}
predicate isSink(DataFlow::Node sink) {
sink.(ReturnNodeExt).getEnclosingCallable() instanceof DataFlowSourceTargetApi
sink instanceof ReturnNodeExt and
getEnclosingCallable(sink) instanceof DataFlowSourceTargetApi
}
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
@@ -1008,8 +1016,8 @@ module MakeModelGenerator<
exists(NodeExtended source, ReturnNodeExt sink, string kind |
PropagateFromSource::flow(source, sink) and
sourceNode(source, kind) and
api = sink.getEnclosingCallable() and
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
api = getEnclosingCallable(sink) and
not irrelevantSourceSinkApi(getEnclosingCallable(source), api) and
result = ModelPrinting::asSourceModel(api, getOutput(sink), kind)
)
}
@@ -1024,7 +1032,7 @@ module MakeModelGenerator<
module PropagateToSinkConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
apiSource(source) and
source.(NodeExtended).getEnclosingCallable() instanceof DataFlowSinkTargetApi
getEnclosingCallable(source) instanceof DataFlowSinkTargetApi
}
predicate isSink(DataFlow::Node sink) {
@@ -1053,7 +1061,7 @@ module MakeModelGenerator<
exists(NodeExtended src, NodeExtended sink, string kind |
PropagateToSink::flow(src, sink) and
sinkNode(sink, kind) and
api = src.getEnclosingCallable() and
api = getEnclosingCallable(src) and
result = ModelPrinting::asSinkModel(api, asInputArgument(src), kind)
)
}