mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into redsun82/rust-pick-edition
This commit is contained in:
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
def test(codeql, actions):
|
||||
codeql.database.create(source_root="src")
|
||||
@@ -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' |
|
||||
@@ -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 |
|
||||
@@ -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' |
|
||||
@@ -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 |
|
||||
5
actions/ql/integration-tests/filters/actions.ql
Normal file
5
actions/ql/integration-tests/filters/actions.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import actions
|
||||
|
||||
from AstNode n
|
||||
where n instanceof Workflow or n instanceof CompositeAction
|
||||
select n
|
||||
@@ -0,0 +1,4 @@
|
||||
paths:
|
||||
- 'included'
|
||||
paths-ignore:
|
||||
- 'excluded'
|
||||
@@ -0,0 +1,2 @@
|
||||
paths-ignore:
|
||||
- 'excluded'
|
||||
@@ -0,0 +1,2 @@
|
||||
paths:
|
||||
- 'included'
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
src/included/action.yml
|
||||
src/included/not-an-action.yml
|
||||
src/included/unreachable-workflow.yml
|
||||
@@ -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
|
||||
@@ -0,0 +1,3 @@
|
||||
src/included/action.yml
|
||||
src/included/not-an-action.yml
|
||||
src/included/unreachable-workflow.yml
|
||||
11
actions/ql/integration-tests/filters/src/excluded/action.yml
Normal file
11
actions/ql/integration-tests/filters/src/excluded/action.yml
Normal 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
|
||||
11
actions/ql/integration-tests/filters/src/included/action.yml
Normal file
11
actions/ql/integration-tests/filters/src/included/action.yml
Normal 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
|
||||
@@ -0,0 +1 @@
|
||||
name: 'Not an action, just a YAML 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
|
||||
@@ -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
|
||||
18
actions/ql/integration-tests/filters/test.py
Executable file
18
actions/ql/integration-tests/filters/test.py
Executable 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")
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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`. */
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Improved autobuilder logic for detecting whether a project references a SDK (and should be built using `dotnet`).
|
||||
@@ -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<>`.
|
||||
*/
|
||||
|
||||
@@ -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%")
|
||||
|
||||
5
javascript/ql/lib/change-notes/2025-04-11-nextrequest.md
Normal file
5
javascript/ql/lib/change-notes/2025-04-11-nextrequest.md
Normal 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`.
|
||||
@@ -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" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
consistencyIssue
|
||||
resultInWrongFile
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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 });
|
||||
}
|
||||
@@ -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 });
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
41
ruby/ql/src/queries/variables/UninitializedLocal.md
Normal file
41
ruby/ql/src/queries/variables/UninitializedLocal.md
Normal 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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
ruby/ql/src/queries/variables/examples/UninitializedLocal.rb
Normal file
14
ruby/ql/src/queries/variables/examples/UninitializedLocal.rb
Normal 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
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,2 @@
|
||||
query: queries/variables/UninitializedLocal.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -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
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -2,16 +2,21 @@
|
||||
| main.rs:6:25:6:30 | ®ex | main.rs:4:20:4:32 | ...::var | main.rs:6:25:6:30 | ®ex | 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 | ®ex | 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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
query: queries/security/CWE-770/UncontrolledAllocationSize.ql
|
||||
postprocess:
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
330
rust/ql/test/query-tests/security/CWE-770/main.rs
Normal file
330
rust/ql/test/query-tests/security/CWE-770/main.rs
Normal 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 ---");
|
||||
}
|
||||
3
rust/ql/test/query-tests/security/CWE-770/options.yml
Normal file
3
rust/ql/test/query-tests/security/CWE-770/options.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
qltest_cargo_check: true
|
||||
qltest_dependencies:
|
||||
- libc = { version = "0.2.11" }
|
||||
@@ -0,0 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "nightly"
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user