mirror of
https://github.com/github/codeql.git
synced 2026-05-27 09:31:30 +02:00
Merge commit '737dd9d4c1' into jb1/lib/dataflowstack
This commit is contained in:
@@ -1,31 +1,197 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Before running this, make sure there is an SSO-enabled token with package:write
|
||||
# permissions to codeql supplied via the GITHUB_TOKEN environment variable
|
||||
help="Usage: ./publish [--override-release] [--dry-run]
|
||||
Publish the automodel query pack.
|
||||
|
||||
AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")"
|
||||
WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.."
|
||||
GRPS="automodel,-test"
|
||||
If no arguments are provided, publish the version of the codeql repo specified by the latest official release of the codeml-automodel repo.
|
||||
If the --override-release argument is provided, your current local HEAD is used (for unofficial releases or patching).
|
||||
If the --dry-run argument is provided, the release is not published (for testing purposes)."
|
||||
|
||||
if [ -z "$CODEQL_DIST" ]; then
|
||||
echo "CODEQL_DIST not set"
|
||||
exit -1
|
||||
# Echo the help message
|
||||
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
|
||||
echo "$help"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd "$AUTOMODEL_ROOT"
|
||||
# Check the number of arguments are valid
|
||||
if [ $# -gt 2 ]; then
|
||||
echo "Error: Invalid arguments provided"
|
||||
echo "$help"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OVERRIDE_RELEASE=0
|
||||
DRY_RUN=0
|
||||
for arg in "$@"
|
||||
do
|
||||
case $arg in
|
||||
--override-release)
|
||||
OVERRIDE_RELEASE=1
|
||||
shift # Remove --override-release from processing
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=1
|
||||
shift # Remove --dry-run from processing
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid argument provided: $arg"
|
||||
echo "$help"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Describe what we're about to do based on the command-line arguments
|
||||
if [ $OVERRIDE_RELEASE = 1 ]; then
|
||||
echo "Publishing the current HEAD of the automodel repo"
|
||||
else
|
||||
echo "Publishing the version of the automodel repo specified by the latest official release of the codeml-automodel repo"
|
||||
fi
|
||||
if [ $DRY_RUN = 1 ]; then
|
||||
echo "Dry run: we will step through the process but we won't publish the query pack"
|
||||
else
|
||||
echo "Not a dry run! Publishing the query pack"
|
||||
fi
|
||||
|
||||
# If we're publishing the codeml-automodel release then we will checkout the sha specified in the release.
|
||||
# So we need to check that there are no uncommitted changes in the local branch.
|
||||
# And, if we're publishing the current HEAD, it's cleaner to ensure that there are no uncommitted changes.
|
||||
if ! git diff --quiet; then
|
||||
echo "Error: Uncommitted changes exist. Please commit or stash your changes before publishing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check the above environment variables are set
|
||||
if [ -z "${GITHUB_TOKEN}" ]; then
|
||||
echo "Error: GITHUB_TOKEN environment variable not set. Please set this to a token with package:write permissions to codeql."
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${GH_TOKEN}" ]; then
|
||||
echo "Error: GH_TOKEN environment variable not set. Please set this to a token with repo permissions to github/codeml-automodel."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the sha of the previous release, i.e. the last commit to the main branch that updated the query pack version
|
||||
PREVIOUS_RELEASE_SHA=$(git rev-list -n 1 main -- ./src/qlpack.yml)
|
||||
if [ -z "$PREVIOUS_RELEASE_SHA" ]; then
|
||||
echo "Error: Could not get the sha of the previous release of codeml-automodel query pack"
|
||||
exit 1
|
||||
else
|
||||
echo "Previous query-pack release sha: $PREVIOUS_RELEASE_SHA"
|
||||
fi
|
||||
|
||||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
CURRENT_SHA=$(git rev-parse HEAD)
|
||||
|
||||
if [ $OVERRIDE_RELEASE = 1 ]; then
|
||||
# Check that the current HEAD is downstream from PREVIOUS_RELEASE_SHA
|
||||
if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$CURRENT_SHA"; then
|
||||
echo "Error: The current HEAD is not downstream from the previous release"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Get the latest release of codeml-automodel
|
||||
TAG_NAME=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/github/codeml-automodel/releases/latest | jq -r .tag_name)
|
||||
# Check TAG_NAME is not empty
|
||||
if [ -z "$TAG_NAME" ]; then
|
||||
echo "Error: Could not get latest release of codeml-automodel"
|
||||
exit 1
|
||||
fi
|
||||
echo "Updating to latest automodel release: $TAG_NAME"
|
||||
# Before downloading, delete any existing release.zip, and ignore failure if not present
|
||||
rm release.zip || true
|
||||
gh release download $TAG_NAME -A zip -O release.zip --repo 'https://github.com/github/codeml-automodel'
|
||||
# Before unzipping, delete any existing release directory, and ignore failure if not present
|
||||
rm -rf release || true
|
||||
unzip -o release.zip -d release
|
||||
REVISION=$(jq -r '.["codeql-sha"]' release/codeml-automodel*/codeml-automodel-release.json)
|
||||
echo "The latest codeml-automodel release specifies the codeql sha $REVISION"
|
||||
# Check that REVISION is downstream from PREVIOUS_RELEASE_SHA
|
||||
if ! git merge-base --is-ancestor "$PREVIOUS_RELEASE_SHA" "$REVISION"; then
|
||||
echo "Error: The codeql version $REVISION is not downstream of the query-pack version $PREVIOUS_RELEASE_SHA"
|
||||
exit 1
|
||||
fi
|
||||
# Get the version of the codeql code specified by the codeml-automodel release
|
||||
git checkout "$REVISION"
|
||||
fi
|
||||
|
||||
# Get the absolute path of the automodel repo
|
||||
AUTOMODEL_ROOT="$(readlink -f "$(dirname $0)")"
|
||||
# Get the absolute path of the workspace root
|
||||
WORKSPACE_ROOT="$AUTOMODEL_ROOT/../../.."
|
||||
# Specify the groups of queries to test and publish
|
||||
GRPS="automodel,-test"
|
||||
|
||||
# Install the codeql gh extension
|
||||
gh extensions install github/gh-codeql
|
||||
|
||||
pushd "$AUTOMODEL_ROOT"
|
||||
echo Testing automodel queries
|
||||
"${CODEQL_DIST}/codeql" test run test
|
||||
gh codeql test run test
|
||||
popd
|
||||
|
||||
cd "$WORKSPACE_ROOT"
|
||||
pushd "$WORKSPACE_ROOT"
|
||||
echo "Preparing the release"
|
||||
gh codeql pack release --groups $GRPS -v
|
||||
|
||||
echo Preparing release
|
||||
"${CODEQL_DIST}/codeql" pack release --groups $GRPS
|
||||
if [ $DRY_RUN = 1 ]; then
|
||||
echo "Dry run: not publishing the query pack"
|
||||
gh codeql pack publish --groups $GRPS --dry-run -v
|
||||
else
|
||||
echo "Not a dry run! Publishing the query pack"
|
||||
gh codeql pack publish --groups $GRPS -v
|
||||
fi
|
||||
|
||||
echo Publishing automodel
|
||||
"${CODEQL_DIST}/codeql" pack publish --groups $GRPS
|
||||
echo "Bumping versions"
|
||||
gh codeql pack post-release --groups $GRPS -v
|
||||
popd
|
||||
|
||||
echo Bumping versions
|
||||
"${CODEQL_DIST}/codeql" pack post-release --groups $GRPS
|
||||
# The above commands update
|
||||
# ./src/CHANGELOG.md
|
||||
# ./src/codeql-pack.release.yml
|
||||
# ./src/qlpack.yml
|
||||
# and add a new file
|
||||
# ./src/change-notes/released/<version>.md
|
||||
|
||||
echo Automodel packs successfully published. Please commit and push the version changes.
|
||||
# Get the filename of the most recently created file in ./src/change-notes/released/*.md
|
||||
# This will be the file for the new release
|
||||
NEW_CHANGE_NOTES_FILE=$(ls -t ./src/change-notes/released/*.md | head -n 1)
|
||||
|
||||
# Make a copy of the modified files
|
||||
mv ./src/CHANGELOG.md ./src/CHANGELOG.md.dry-run
|
||||
mv ./src/codeql-pack.release.yml ./src/codeql-pack.release.yml.dry-run
|
||||
mv ./src/qlpack.yml ./src/qlpack.yml.dry-run
|
||||
mv "$NEW_CHANGE_NOTES_FILE" ./src/change-notes/released.md.dry-run
|
||||
|
||||
if [ $OVERRIDE_RELEASE = 1 ]; then
|
||||
# Restore the original files
|
||||
git checkout ./src/CHANGELOG.md
|
||||
git checkout ./src/codeql-pack.release.yml
|
||||
git checkout ./src/qlpack.yml
|
||||
else
|
||||
# Restore the original files
|
||||
git checkout "$CURRENT_BRANCH" --force
|
||||
fi
|
||||
|
||||
if [ $DRY_RUN = 1 ]; then
|
||||
echo "Inspect the updated dry-run version files:"
|
||||
ls -l ./src/*.dry-run
|
||||
ls -l ./src/change-notes/*.dry-run
|
||||
else
|
||||
# Add the updated files to the current branch
|
||||
echo "Adding the version changes"
|
||||
mv -f ./src/CHANGELOG.md.dry-run ./src/CHANGELOG.md
|
||||
mv -f ./src/codeql-pack.release.yml.dry-run ./src/codeql-pack.release.yml
|
||||
mv -f ./src/qlpack.yml.dry-run ./src/qlpack.yml
|
||||
mv -f ./src/change-notes/released.md.dry-run "$NEW_CHANGE_NOTES_FILE"
|
||||
git add ./src/CHANGELOG.md
|
||||
git add ./src/codeql-pack.release.yml
|
||||
git add ./src/qlpack.yml
|
||||
git add "$NEW_CHANGE_NOTES_FILE"
|
||||
echo "Added the following updated version files to the current branch:"
|
||||
git status -s
|
||||
echo "To complete the release, please commit these files and merge to the main branch"
|
||||
fi
|
||||
|
||||
echo "Done"
|
||||
@@ -15,7 +15,6 @@ private import semmle.code.java.security.QueryInjection
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
|
||||
private import AutomodelJavaUtil as AutomodelJavaUtil
|
||||
private import semmle.code.java.security.PathSanitizer as PathSanitizer
|
||||
private import AutomodelSharedGetCallable as AutomodelSharedGetCallable
|
||||
import AutomodelSharedCharacteristics as SharedCharacteristics
|
||||
import AutomodelEndpointTypes as AutomodelEndpointTypes
|
||||
|
||||
@@ -26,14 +25,18 @@ newtype JavaRelatedLocationType =
|
||||
|
||||
newtype TApplicationModeEndpoint =
|
||||
TExplicitArgument(Call call, DataFlow::Node arg) {
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
exists(Argument argExpr |
|
||||
arg.asExpr() = argExpr and call = argExpr.getCall() and not argExpr.isVararg()
|
||||
)
|
||||
} or
|
||||
TInstanceArgument(Call call, DataFlow::Node arg) {
|
||||
arg = DataFlow::getInstanceArgument(call) and not call instanceof ConstructorCall
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
arg = DataFlow::getInstanceArgument(call) and
|
||||
not call instanceof ConstructorCall
|
||||
} or
|
||||
TImplicitVarargsArray(Call call, DataFlow::Node arg, int idx) {
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
exists(Argument argExpr |
|
||||
arg.asExpr() = argExpr and
|
||||
call.getArgument(idx) = argExpr and
|
||||
@@ -41,8 +44,12 @@ newtype TApplicationModeEndpoint =
|
||||
not exists(int i | i < idx and call.getArgument(i).(Argument).isVararg())
|
||||
)
|
||||
} or
|
||||
TMethodReturnValue(Call call) { not call instanceof ConstructorCall } or
|
||||
TMethodReturnValue(Call call) {
|
||||
AutomodelJavaUtil::isFromSource(call) and
|
||||
not call instanceof ConstructorCall
|
||||
} or
|
||||
TOverriddenParameter(Parameter p, Method overriddenMethod) {
|
||||
AutomodelJavaUtil::isFromSource(p) and
|
||||
not p.getCallable().callsConstructor(_) and
|
||||
p.getCallable().(Method).overrides(overriddenMethod)
|
||||
}
|
||||
@@ -56,8 +63,6 @@ abstract private class ApplicationModeEndpoint extends TApplicationModeEndpoint
|
||||
*/
|
||||
abstract Callable getCallable();
|
||||
|
||||
abstract Call getCall();
|
||||
|
||||
/**
|
||||
* Gets the input (if any) for this endpoint, eg.: `Argument[0]`.
|
||||
*
|
||||
@@ -91,50 +96,50 @@ abstract private class ApplicationModeEndpoint extends TApplicationModeEndpoint
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
class TCallArgument = TExplicitArgument or TInstanceArgument or TImplicitVarargsArray;
|
||||
|
||||
/**
|
||||
* A class representing nodes that are arguments to calls.
|
||||
* An endpoint that represents an "argument" to a call in a broad sense, including
|
||||
* both explicit arguments and the instance argument.
|
||||
*/
|
||||
class ExplicitArgument extends ApplicationModeEndpoint, TExplicitArgument {
|
||||
abstract class CallArgument extends ApplicationModeEndpoint, TCallArgument {
|
||||
Call call;
|
||||
DataFlow::Node arg;
|
||||
|
||||
ExplicitArgument() { this = TExplicitArgument(call, arg) }
|
||||
|
||||
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
|
||||
|
||||
override Call getCall() { result = call }
|
||||
override string getMaDOutput() { none() }
|
||||
|
||||
override DataFlow::Node asNode() { result = arg }
|
||||
|
||||
Call getCall() { result = call }
|
||||
|
||||
override string toString() { result = arg.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An endpoint that represents an explicit argument to a call.
|
||||
*/
|
||||
class ExplicitArgument extends CallArgument, TExplicitArgument {
|
||||
ExplicitArgument() { this = TExplicitArgument(call, arg) }
|
||||
|
||||
private int getArgIndex() { this.asTop() = call.getArgument(result) }
|
||||
|
||||
override string getMaDInput() { result = "Argument[" + this.getArgIndex() + "]" }
|
||||
|
||||
override string getMaDOutput() { none() }
|
||||
|
||||
override Top asTop() { result = arg.asExpr() }
|
||||
|
||||
override DataFlow::Node asNode() { result = arg }
|
||||
|
||||
override string toString() { result = arg.toString() }
|
||||
}
|
||||
|
||||
class InstanceArgument extends ApplicationModeEndpoint, TInstanceArgument {
|
||||
Call call;
|
||||
DataFlow::Node arg;
|
||||
|
||||
/**
|
||||
* An endpoint that represents the instance argument to a call.
|
||||
*/
|
||||
class InstanceArgument extends CallArgument, TInstanceArgument {
|
||||
InstanceArgument() { this = TInstanceArgument(call, arg) }
|
||||
|
||||
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
|
||||
|
||||
override Call getCall() { result = call }
|
||||
|
||||
override string getMaDInput() { result = "Argument[this]" }
|
||||
|
||||
override string getMaDOutput() { none() }
|
||||
|
||||
override Top asTop() { if exists(arg.asExpr()) then result = arg.asExpr() else result = call }
|
||||
|
||||
override DataFlow::Node asNode() { result = arg }
|
||||
|
||||
override string toString() { result = arg.toString() }
|
||||
}
|
||||
|
||||
@@ -147,26 +152,14 @@ class InstanceArgument extends ApplicationModeEndpoint, TInstanceArgument {
|
||||
* In order to be able to distinguish between varargs endpoints and regular endpoints, we export the `isVarargsArray`
|
||||
* meta data field in the extraction queries.
|
||||
*/
|
||||
class ImplicitVarargsArray extends ApplicationModeEndpoint, TImplicitVarargsArray {
|
||||
Call call;
|
||||
DataFlow::Node vararg;
|
||||
class ImplicitVarargsArray extends CallArgument, TImplicitVarargsArray {
|
||||
int idx;
|
||||
|
||||
ImplicitVarargsArray() { this = TImplicitVarargsArray(call, vararg, idx) }
|
||||
|
||||
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
|
||||
|
||||
override Call getCall() { result = call }
|
||||
ImplicitVarargsArray() { this = TImplicitVarargsArray(call, arg, idx) }
|
||||
|
||||
override string getMaDInput() { result = "Argument[" + idx + "]" }
|
||||
|
||||
override string getMaDOutput() { none() }
|
||||
|
||||
override Top asTop() { result = call }
|
||||
|
||||
override DataFlow::Node asNode() { result = vararg }
|
||||
|
||||
override string toString() { result = vararg.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -180,8 +173,6 @@ class MethodReturnValue extends ApplicationModeEndpoint, TMethodReturnValue {
|
||||
|
||||
override Callable getCallable() { result = call.getCallee().getSourceDeclaration() }
|
||||
|
||||
override Call getCall() { result = call }
|
||||
|
||||
override string getMaDInput() { none() }
|
||||
|
||||
override string getMaDOutput() { result = "ReturnValue" }
|
||||
@@ -211,8 +202,6 @@ class OverriddenParameter extends ApplicationModeEndpoint, TOverriddenParameter
|
||||
result = overriddenMethod.getSourceDeclaration()
|
||||
}
|
||||
|
||||
override Call getCall() { none() }
|
||||
|
||||
private int getArgIndex() { p.getCallable().getParameter(result) = p }
|
||||
|
||||
override string getMaDInput() { none() }
|
||||
@@ -239,7 +228,9 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
|
||||
class EndpointType = AutomodelEndpointTypes::EndpointType;
|
||||
|
||||
class NegativeEndpointType = AutomodelEndpointTypes::NegativeSinkType;
|
||||
class SinkType = AutomodelEndpointTypes::SinkType;
|
||||
|
||||
class SourceType = AutomodelEndpointTypes::SourceType;
|
||||
|
||||
class RelatedLocation = Location::Top;
|
||||
|
||||
@@ -248,13 +239,12 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
// Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact.
|
||||
predicate isSanitizer(Endpoint e, EndpointType t) {
|
||||
exists(t) and
|
||||
(
|
||||
e.asNode().getType() instanceof BoxedType
|
||||
or
|
||||
e.asNode().getType() instanceof PrimitiveType
|
||||
or
|
||||
e.asNode().getType() instanceof NumberType
|
||||
)
|
||||
AutomodelJavaUtil::isUnexploitableType([
|
||||
// for most endpoints, we can get the type from the node
|
||||
e.asNode().getType(),
|
||||
// but not for calls to void methods, where we need to go via the AST
|
||||
e.asTop().(Expr).getType()
|
||||
])
|
||||
or
|
||||
t instanceof AutomodelEndpointTypes::PathInjectionSinkType and
|
||||
e.asNode() instanceof PathSanitizer::PathInjectionSanitizer
|
||||
@@ -316,7 +306,7 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
*/
|
||||
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
|
||||
type = CallContext() and
|
||||
result = e.getCall()
|
||||
result = e.(CallArgument).getCall()
|
||||
or
|
||||
type = MethodDoc() and
|
||||
result = e.getCallable().(Documentable).getJavadoc()
|
||||
@@ -326,22 +316,6 @@ module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig
|
||||
}
|
||||
}
|
||||
|
||||
private class JavaCallable = Callable;
|
||||
|
||||
private module ApplicationModeGetCallable implements AutomodelSharedGetCallable::GetCallableSig {
|
||||
class Callable = JavaCallable;
|
||||
|
||||
class Endpoint = ApplicationCandidatesImpl::Endpoint;
|
||||
|
||||
/**
|
||||
* Returns the API callable being modeled.
|
||||
*
|
||||
* We usually want to use `.getSourceDeclaration()` instead of just 'the' callable,
|
||||
* because the source declaration callable has erased generic type parameters.
|
||||
*/
|
||||
Callable getCallable(Endpoint e) { result = e.getCall().getCallee() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains endpoints that are defined in QL code rather than as a MaD model. Ideally this predicate
|
||||
* should be empty.
|
||||
@@ -369,10 +343,10 @@ class ApplicationModeMetadataExtractor extends string {
|
||||
|
||||
predicate hasMetadata(
|
||||
Endpoint e, string package, string type, string subtypes, string name, string signature,
|
||||
string input, string output, string isVarargsArray
|
||||
string input, string output, string isVarargsArray, string alreadyAiModeled,
|
||||
string extensibleType
|
||||
) {
|
||||
exists(Callable callable |
|
||||
e.getCallable() = callable and
|
||||
exists(Callable callable | e.getCallable() = callable |
|
||||
(if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and
|
||||
(if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and
|
||||
package = callable.getDeclaringType().getPackage().getName() and
|
||||
@@ -382,19 +356,107 @@ class ApplicationModeMetadataExtractor extends string {
|
||||
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
|
||||
name = callable.getName() and
|
||||
signature = ExternalFlow::paramsString(callable) and
|
||||
if e instanceof ImplicitVarargsArray
|
||||
then isVarargsArray = "true"
|
||||
else isVarargsArray = "false"
|
||||
(
|
||||
if e instanceof ImplicitVarargsArray
|
||||
then isVarargsArray = "true"
|
||||
else isVarargsArray = "false"
|
||||
) and
|
||||
extensibleType = e.getExtensibleType()
|
||||
) and
|
||||
(
|
||||
not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = ""
|
||||
or
|
||||
CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` should be considered a candidate for the `extensibleType`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isCandidate(
|
||||
Endpoint endpoint, string package, string type, string subtypes, string name, string signature,
|
||||
string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled
|
||||
) {
|
||||
CharacteristicsImpl::isCandidate(endpoint, _) and
|
||||
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
|
||||
u.appliesToEndpoint(endpoint)
|
||||
) and
|
||||
any(ApplicationModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargs,
|
||||
alreadyAiModeled, extensibleType) and
|
||||
// If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a
|
||||
// candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's
|
||||
// already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We
|
||||
// assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink
|
||||
// types, and we don't need to reexamine it.
|
||||
alreadyAiModeled.matches(["", "%ai-%"]) and
|
||||
AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` is a negative example for the `extensibleType`
|
||||
* because of the `characteristic`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isNegativeExample(
|
||||
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
|
||||
string type, string subtypes, string name, string signature, string input, string output,
|
||||
string isVarargsArray, string extensibleType
|
||||
) {
|
||||
characteristic.appliesToEndpoint(endpoint) and
|
||||
// the node is known not to be an endpoint of any appropriate type
|
||||
forall(AutomodelEndpointTypes::EndpointType tp |
|
||||
tp = CharacteristicsImpl::getAPotentialType(endpoint)
|
||||
|
|
||||
characteristic.hasImplications(tp, false, _)
|
||||
) and
|
||||
// the lowest confidence across all endpoint types should be at least highConfidence
|
||||
confidence =
|
||||
min(float c |
|
||||
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
|
||||
) and
|
||||
confidence >= SharedCharacteristics::highConfidence() and
|
||||
any(ApplicationModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
|
||||
isVarargsArray, _, extensibleType) and
|
||||
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
|
||||
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
|
||||
not exists(EndpointCharacteristic characteristic2, float confidence2 |
|
||||
characteristic2 != characteristic
|
||||
|
|
||||
characteristic2.appliesToEndpoint(endpoint) and
|
||||
confidence2 >= SharedCharacteristics::maximalConfidence() and
|
||||
characteristic2
|
||||
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` is a positive example for the `endpointType`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isPositiveExample(
|
||||
Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name,
|
||||
string signature, string input, string output, string isVarargsArray, string extensibleType
|
||||
) {
|
||||
any(ApplicationModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output,
|
||||
isVarargsArray, _, extensibleType) and
|
||||
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and
|
||||
exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()))
|
||||
}
|
||||
|
||||
/*
|
||||
* EndpointCharacteristic classes that are specific to Automodel for Java.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an is-style boolean method is unexploitable even if it is a sink.
|
||||
* A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks.
|
||||
*
|
||||
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
|
||||
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
|
||||
@@ -406,15 +468,15 @@ private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASin
|
||||
UnexploitableIsCharacteristic() { this = "unexploitable (is-style boolean method)" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
not ApplicationCandidatesImpl::isSink(e, _, _) and
|
||||
e.getCallable().getName().matches("is%") and
|
||||
e.getCallable().getReturnType() instanceof BooleanType
|
||||
e.getCallable().getReturnType() instanceof BooleanType and
|
||||
not ApplicationCandidatesImpl::isSink(e, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an existence-checking boolean method is unexploitable even if it is a
|
||||
* sink.
|
||||
* A negative characteristic that indicates that parameters of an existence-checking boolean method should not be
|
||||
* considered sinks.
|
||||
*
|
||||
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
|
||||
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
|
||||
@@ -424,9 +486,7 @@ private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::Not
|
||||
UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
not ApplicationCandidatesImpl::isSink(e, _, _) and
|
||||
exists(Callable callable |
|
||||
callable = ApplicationModeGetCallable::getCallable(e) and
|
||||
exists(Callable callable | callable = e.getCallable() |
|
||||
callable.getName().toLowerCase() = ["exists", "notexists"] and
|
||||
callable.getReturnType() instanceof BooleanType
|
||||
)
|
||||
@@ -434,14 +494,23 @@ private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::Not
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an endpoint is an argument to an exception, which is not a sink.
|
||||
* A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks,
|
||||
* and its return value should not be considered a source.
|
||||
*/
|
||||
private class ExceptionCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
|
||||
private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
|
||||
{
|
||||
ExceptionCharacteristic() { this = "exception" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
ApplicationModeGetCallable::getCallable(e).getDeclaringType().getASupertype*() instanceof
|
||||
TypeThrowable
|
||||
e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and
|
||||
(
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not ApplicationCandidatesImpl::isSink(e, _, _)
|
||||
or
|
||||
e.getExtensibleType() = "sourceModel" and
|
||||
not ApplicationCandidatesImpl::isSource(e, _, _) and
|
||||
e.getMaDOutput() = "ReturnValue"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,7 +523,6 @@ private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASink
|
||||
IsMaDTaintStepCharacteristic() { this = "taint step" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e.asNode(), _, _)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e.asNode(), _, _)
|
||||
@@ -475,18 +543,20 @@ private class LocalCall extends CharacteristicsImpl::UninterestingToModelCharact
|
||||
LocalCall() { this = "local call" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
ApplicationModeGetCallable::getCallable(e).fromSource()
|
||||
e.(CallArgument).getCallable().fromSource()
|
||||
or
|
||||
e.(MethodReturnValue).getCallable().fromSource()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Characteristic that marks endpoints as uninteresting to model, according to the Java ModelExclusions module.
|
||||
* A characteristic that marks endpoints as uninteresting to model, according to the Java ModelExclusions module.
|
||||
*/
|
||||
private class ExcludedFromModeling extends CharacteristicsImpl::UninterestingToModelCharacteristic {
|
||||
ExcludedFromModeling() { this = "excluded from modeling" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
ModelExclusions::isUninterestingForModels(ApplicationModeGetCallable::getCallable(e))
|
||||
ModelExclusions::isUninterestingForModels(e.getCallable())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,8 +569,7 @@ private class NonPublicMethodCharacteristic extends CharacteristicsImpl::Uninter
|
||||
NonPublicMethodCharacteristic() { this = "non-public method" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not ApplicationModeGetCallable::getCallable(e).isPublic()
|
||||
exists(Callable c | c = e.getCallable() | not c.isPublic())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,11 +591,10 @@ private class OtherArgumentToModeledMethodCharacteristic extends Characteristics
|
||||
}
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not ApplicationCandidatesImpl::isSink(e, _, _) and
|
||||
exists(Endpoint otherSink |
|
||||
exists(CallArgument otherSink |
|
||||
ApplicationCandidatesImpl::isSink(otherSink, _, "manual") and
|
||||
e.getCall() = otherSink.getCall() and
|
||||
e.(CallArgument).getCall() = otherSink.getCall() and
|
||||
e != otherSink
|
||||
)
|
||||
}
|
||||
@@ -540,10 +608,7 @@ private class OtherArgumentToModeledMethodCharacteristic extends Characteristics
|
||||
private class FunctionValueCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic {
|
||||
FunctionValueCharacteristic() { this = "function value" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
e.asNode().asExpr() instanceof FunctionalExpr
|
||||
}
|
||||
override predicate appliesToEndpoint(Endpoint e) { e.asNode().asExpr() instanceof FunctionalExpr }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -557,10 +622,7 @@ private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyN
|
||||
{
|
||||
CannotBeTaintedCharacteristic() { this = "cannot be tainted" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not this.isKnownOutNodeForStep(e)
|
||||
}
|
||||
override predicate appliesToEndpoint(Endpoint e) { not this.isKnownOutNodeForStep(e) }
|
||||
|
||||
/**
|
||||
* Holds if the node `n` is known as the predecessor in a modeled flow step.
|
||||
|
||||
@@ -25,20 +25,20 @@ private import AutomodelJavaUtil
|
||||
bindingset[limit]
|
||||
private Endpoint getSampleForSignature(
|
||||
int limit, string package, string type, string subtypes, string name, string signature,
|
||||
string input, string output, string isVarargs, string extensibleType
|
||||
string input, string output, string isVarargs, string extensibleType, string alreadyAiModeled
|
||||
) {
|
||||
exists(int n, int num_endpoints, ApplicationModeMetadataExtractor meta |
|
||||
num_endpoints =
|
||||
count(Endpoint e |
|
||||
e.getExtensibleType() = extensibleType and
|
||||
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs)
|
||||
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs,
|
||||
alreadyAiModeled, extensibleType)
|
||||
)
|
||||
|
|
||||
result =
|
||||
rank[n](Endpoint e, Location loc |
|
||||
loc = e.asTop().getLocation() and
|
||||
e.getExtensibleType() = extensibleType and
|
||||
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs)
|
||||
meta.hasMetadata(e, package, type, subtypes, name, signature, input, output, isVarargs,
|
||||
alreadyAiModeled, extensibleType)
|
||||
|
|
||||
e
|
||||
order by
|
||||
@@ -55,31 +55,15 @@ private Endpoint getSampleForSignature(
|
||||
}
|
||||
|
||||
from
|
||||
Endpoint endpoint, ApplicationModeMetadataExtractor meta, DollarAtString package,
|
||||
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
|
||||
DollarAtString input, DollarAtString output, DollarAtString isVarargsArray,
|
||||
DollarAtString alreadyAiModeled, DollarAtString extensibleType
|
||||
Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes,
|
||||
DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString isVarargsArray, DollarAtString alreadyAiModeled, DollarAtString extensibleType
|
||||
where
|
||||
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
|
||||
u.appliesToEndpoint(endpoint)
|
||||
) and
|
||||
CharacteristicsImpl::isSinkCandidate(endpoint, _) and
|
||||
isCandidate(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray,
|
||||
extensibleType, alreadyAiModeled) and
|
||||
endpoint =
|
||||
getSampleForSignature(9, package, type, subtypes, name, signature, input, output,
|
||||
isVarargsArray, extensibleType) and
|
||||
// If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a
|
||||
// candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's
|
||||
// already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We
|
||||
// assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink
|
||||
// types, and we don't need to reexamine it.
|
||||
(
|
||||
not CharacteristicsImpl::isModeled(endpoint, _, _, _) and alreadyAiModeled = ""
|
||||
or
|
||||
alreadyAiModeled.matches("%ai-%") and
|
||||
CharacteristicsImpl::isModeled(endpoint, _, _, alreadyAiModeled)
|
||||
) and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray) and
|
||||
includeAutomodelCandidate(package, type, name, signature)
|
||||
isVarargsArray, extensibleType, alreadyAiModeled)
|
||||
select endpoint.asNode(),
|
||||
"Related locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
|
||||
|
||||
@@ -42,25 +42,13 @@ Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) {
|
||||
|
||||
from
|
||||
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
|
||||
ApplicationModeMetadataExtractor meta, DollarAtString package, DollarAtString type,
|
||||
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input,
|
||||
DollarAtString output, DollarAtString isVarargsArray, DollarAtString extensibleType
|
||||
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
|
||||
DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString isVarargsArray, DollarAtString extensibleType
|
||||
where
|
||||
endpoint = getSampleForCharacteristic(characteristic, 100) and
|
||||
extensibleType = endpoint.getExtensibleType() and
|
||||
confidence >= SharedCharacteristics::highConfidence() and
|
||||
characteristic.hasImplications(any(NegativeSinkType negative), true, confidence) and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray) and
|
||||
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
|
||||
// treated by the actual query as a sanitizer, since the final logic is something like
|
||||
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
|
||||
// they're ambiguous and might confuse the model, so we explicitly exclude all known sinks from the negative examples.
|
||||
not exists(EndpointCharacteristic characteristic2, float confidence2, SinkType positiveType |
|
||||
not positiveType instanceof NegativeSinkType and
|
||||
characteristic2.appliesToEndpoint(endpoint) and
|
||||
confidence2 >= SharedCharacteristics::maximalConfidence() and
|
||||
characteristic2.hasImplications(positiveType, true, confidence2)
|
||||
) and
|
||||
isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature,
|
||||
input, output, isVarargsArray, extensibleType) and
|
||||
message = characteristic
|
||||
select endpoint.asNode(),
|
||||
message + "\nrelated locations: $@, $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
|
||||
@@ -18,11 +18,8 @@ from
|
||||
DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString isVarargsArray, DollarAtString extensibleType
|
||||
where
|
||||
extensibleType = endpoint.getExtensibleType() and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, isVarargsArray) and
|
||||
// Extract positive examples of sinks belonging to the existing ATM query configurations.
|
||||
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _) and
|
||||
exists(CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()))
|
||||
isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output,
|
||||
isVarargsArray, extensibleType)
|
||||
select endpoint.asNode(),
|
||||
endpointType + "\nrelated locations: $@, $@, $@." +
|
||||
"\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
|
||||
@@ -30,11 +30,6 @@ abstract class SinkType extends EndpointType {
|
||||
SinkType() { any() }
|
||||
}
|
||||
|
||||
/** The `Negative` class for non-sinks. */
|
||||
class NegativeSinkType extends SinkType {
|
||||
NegativeSinkType() { this = "non-sink" }
|
||||
}
|
||||
|
||||
/** A sink relevant to the SQL injection query */
|
||||
class SqlInjectionSinkType extends SinkType {
|
||||
SqlInjectionSinkType() { this = "sql-injection" }
|
||||
|
||||
@@ -15,7 +15,6 @@ private import semmle.code.java.security.QueryInjection
|
||||
private import semmle.code.java.security.RequestForgery
|
||||
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
|
||||
private import AutomodelJavaUtil as AutomodelJavaUtil
|
||||
private import AutomodelSharedGetCallable as AutomodelSharedGetCallable
|
||||
import AutomodelSharedCharacteristics as SharedCharacteristics
|
||||
import AutomodelEndpointTypes as AutomodelEndpointTypes
|
||||
|
||||
@@ -25,32 +24,29 @@ newtype JavaRelatedLocationType =
|
||||
|
||||
newtype TFrameworkModeEndpoint =
|
||||
TExplicitParameter(Parameter p) {
|
||||
not p.getType() instanceof PrimitiveType and
|
||||
not p.getType() instanceof BoxedType and
|
||||
not p.getType() instanceof NumberType
|
||||
AutomodelJavaUtil::isFromSource(p) and
|
||||
not AutomodelJavaUtil::isUnexploitableType(p.getType())
|
||||
} or
|
||||
TQualifier(Callable c) { not c instanceof Constructor } or
|
||||
TQualifier(Callable c) { AutomodelJavaUtil::isFromSource(c) and not c instanceof Constructor } or
|
||||
TReturnValue(Callable c) {
|
||||
AutomodelJavaUtil::isFromSource(c) and
|
||||
c instanceof Constructor
|
||||
or
|
||||
AutomodelJavaUtil::isFromSource(c) and
|
||||
c instanceof Method and
|
||||
(
|
||||
not c.getReturnType() instanceof VoidType and
|
||||
not c.getReturnType() instanceof PrimitiveType
|
||||
)
|
||||
not AutomodelJavaUtil::isUnexploitableType(c.getReturnType())
|
||||
} or
|
||||
TOverridableParameter(Method m, Parameter p) {
|
||||
AutomodelJavaUtil::isFromSource(p) and
|
||||
not AutomodelJavaUtil::isUnexploitableType(p.getType()) and
|
||||
p.getCallable() = m and
|
||||
m instanceof ModelExclusions::ModelApi and
|
||||
not m.getDeclaringType().isFinal() and
|
||||
not m.isFinal() and
|
||||
not m.isStatic()
|
||||
AutomodelJavaUtil::isOverridable(m)
|
||||
} or
|
||||
TOverridableQualifier(Method m) {
|
||||
AutomodelJavaUtil::isFromSource(m) and
|
||||
m instanceof ModelExclusions::ModelApi and
|
||||
not m.getDeclaringType().isFinal() and
|
||||
not m.isFinal() and
|
||||
not m.isStatic()
|
||||
AutomodelJavaUtil::isOverridable(m)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +75,7 @@ abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
|
||||
/**
|
||||
* Returns the callable that contains the endpoint.
|
||||
*/
|
||||
abstract Callable getEnclosingCallable();
|
||||
abstract Callable getCallable();
|
||||
|
||||
abstract Top asTop();
|
||||
|
||||
@@ -101,7 +97,7 @@ class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParamete
|
||||
|
||||
override string getParamName() { result = param.getName() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = param.getCallable() }
|
||||
override Callable getCallable() { result = param.getCallable() }
|
||||
|
||||
override Top asTop() { result = param }
|
||||
|
||||
@@ -121,7 +117,7 @@ class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
|
||||
|
||||
override string getParamName() { result = "this" }
|
||||
|
||||
override Callable getEnclosingCallable() { result = callable }
|
||||
override Callable getCallable() { result = callable }
|
||||
|
||||
override Top asTop() { result = callable }
|
||||
|
||||
@@ -139,7 +135,7 @@ class ReturnValue extends FrameworkModeEndpoint, TReturnValue {
|
||||
|
||||
override string getParamName() { none() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = callable }
|
||||
override Callable getCallable() { result = callable }
|
||||
|
||||
override Top asTop() { result = callable }
|
||||
|
||||
@@ -158,7 +154,7 @@ class OverridableParameter extends FrameworkModeEndpoint, TOverridableParameter
|
||||
|
||||
override string getParamName() { result = param.getName() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = method }
|
||||
override Callable getCallable() { result = method }
|
||||
|
||||
override Top asTop() { result = param }
|
||||
|
||||
@@ -176,7 +172,7 @@ class OverridableQualifier extends FrameworkModeEndpoint, TOverridableQualifier
|
||||
|
||||
override string getParamName() { result = "this" }
|
||||
|
||||
override Callable getEnclosingCallable() { result = m }
|
||||
override Callable getCallable() { result = m }
|
||||
|
||||
override Top asTop() { result = m }
|
||||
|
||||
@@ -197,7 +193,9 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
|
||||
class EndpointType = AutomodelEndpointTypes::EndpointType;
|
||||
|
||||
class NegativeEndpointType = AutomodelEndpointTypes::NegativeSinkType;
|
||||
class SinkType = AutomodelEndpointTypes::SinkType;
|
||||
|
||||
class SourceType = AutomodelEndpointTypes::SourceType;
|
||||
|
||||
class RelatedLocation = Location::Top;
|
||||
|
||||
@@ -239,8 +237,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
additional predicate sinkSpec(
|
||||
Endpoint e, string package, string type, string name, string signature, string ext, string input
|
||||
) {
|
||||
e.getEnclosingCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getEnclosingCallable()) and
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
ext = "" and
|
||||
input = e.getMaDInput()
|
||||
}
|
||||
@@ -249,8 +247,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
Endpoint e, string package, string type, string name, string signature, string ext,
|
||||
string output
|
||||
) {
|
||||
e.getEnclosingCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getEnclosingCallable()) and
|
||||
e.getCallable().hasQualifiedName(package, type, name) and
|
||||
signature = ExternalFlow::paramsString(e.getCallable()) and
|
||||
ext = "" and
|
||||
output = e.getMaDOutput()
|
||||
}
|
||||
@@ -262,10 +260,10 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
|
||||
*/
|
||||
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
|
||||
type = MethodDoc() and
|
||||
result = e.getEnclosingCallable().(Documentable).getJavadoc()
|
||||
result = e.getCallable().(Documentable).getJavadoc()
|
||||
or
|
||||
type = ClassDoc() and
|
||||
result = e.getEnclosingCallable().getDeclaringType().(Documentable).getJavadoc()
|
||||
result = e.getCallable().getDeclaringType().(Documentable).getJavadoc()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,25 +285,116 @@ class FrameworkModeMetadataExtractor extends string {
|
||||
|
||||
predicate hasMetadata(
|
||||
Endpoint e, string package, string type, string subtypes, string name, string signature,
|
||||
string input, string output, string parameterName
|
||||
string input, string output, string parameterName, string alreadyAiModeled,
|
||||
string extensibleType
|
||||
) {
|
||||
(if exists(e.getParamName()) then parameterName = e.getParamName() else parameterName = "") and
|
||||
name = e.getEnclosingCallable().getName() and
|
||||
(if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and
|
||||
(if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and
|
||||
package = e.getEnclosingCallable().getDeclaringType().getPackage().getName() and
|
||||
type = e.getEnclosingCallable().getDeclaringType().getErasure().(RefType).nestedName() and
|
||||
subtypes = AutomodelJavaUtil::considerSubtypes(e.getEnclosingCallable()).toString() and
|
||||
signature = ExternalFlow::paramsString(e.getEnclosingCallable())
|
||||
exists(Callable callable | e.getCallable() = callable |
|
||||
(if exists(e.getMaDInput()) then input = e.getMaDInput() else input = "") and
|
||||
(if exists(e.getMaDOutput()) then output = e.getMaDOutput() else output = "") and
|
||||
package = callable.getDeclaringType().getPackage().getName() and
|
||||
// we're using the erased types because the MaD convention is to not specify type parameters.
|
||||
// Whether something is or isn't a sink doesn't usually depend on the type parameters.
|
||||
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
|
||||
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
|
||||
name = callable.getName() and
|
||||
signature = ExternalFlow::paramsString(callable) and
|
||||
(if exists(e.getParamName()) then parameterName = e.getParamName() else parameterName = "") and
|
||||
e.getExtensibleType() = extensibleType
|
||||
) and
|
||||
(
|
||||
not CharacteristicsImpl::isModeled(e, _, extensibleType, _) and alreadyAiModeled = ""
|
||||
or
|
||||
CharacteristicsImpl::isModeled(e, _, extensibleType, alreadyAiModeled)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` should be considered a candidate for the `extensibleType`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isCandidate(
|
||||
Endpoint endpoint, string package, string type, string subtypes, string name, string signature,
|
||||
string input, string output, string parameterName, string extensibleType, string alreadyAiModeled
|
||||
) {
|
||||
CharacteristicsImpl::isCandidate(endpoint, _) and
|
||||
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
|
||||
u.appliesToEndpoint(endpoint)
|
||||
) and
|
||||
any(FrameworkModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
|
||||
alreadyAiModeled, extensibleType) and
|
||||
// If a node is already modeled in MaD, we don't include it as a candidate. Otherwise, we might include it as a
|
||||
// candidate for query A, but the model will label it as a sink for one of the sink types of query B, for which it's
|
||||
// already a known sink. This would result in overlap between our detected sinks and the pre-existing modeling. We
|
||||
// assume that, if a sink has already been modeled in a MaD model, then it doesn't belong to any additional sink
|
||||
// types, and we don't need to reexamine it.
|
||||
alreadyAiModeled.matches(["", "%ai-%"]) and
|
||||
AutomodelJavaUtil::includeAutomodelCandidate(package, type, name, signature)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` is a negative example for the `extensibleType`
|
||||
* because of the `characteristic`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isNegativeExample(
|
||||
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string package,
|
||||
string type, string subtypes, string name, string signature, string input, string output,
|
||||
string parameterName, string extensibleType
|
||||
) {
|
||||
characteristic.appliesToEndpoint(endpoint) and
|
||||
// the node is known not to be an endpoint of any appropriate type
|
||||
forall(AutomodelEndpointTypes::EndpointType tp |
|
||||
tp = CharacteristicsImpl::getAPotentialType(endpoint)
|
||||
|
|
||||
characteristic.hasImplications(tp, false, _)
|
||||
) and
|
||||
// the lowest confidence across all endpoint types should be at least highConfidence
|
||||
confidence =
|
||||
min(float c |
|
||||
characteristic.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), false, c)
|
||||
) and
|
||||
confidence >= SharedCharacteristics::highConfidence() and
|
||||
any(FrameworkModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
|
||||
_, extensibleType) and
|
||||
// It's valid for a node to be both a potential source/sanitizer and a sink. We don't want to include such nodes
|
||||
// as negative examples in the prompt, because they're ambiguous and might confuse the model, so we explicitly exclude them here.
|
||||
not exists(EndpointCharacteristic characteristic2, float confidence2 |
|
||||
characteristic2 != characteristic
|
||||
|
|
||||
characteristic2.appliesToEndpoint(endpoint) and
|
||||
confidence2 >= SharedCharacteristics::maximalConfidence() and
|
||||
characteristic2
|
||||
.hasImplications(CharacteristicsImpl::getAPotentialType(endpoint), true, confidence2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` is a positive example for the `endpointType`.
|
||||
*
|
||||
* The other parameters record various other properties of interest.
|
||||
*/
|
||||
predicate isPositiveExample(
|
||||
Endpoint endpoint, string endpointType, string package, string type, string subtypes, string name,
|
||||
string signature, string input, string output, string parameterName, string extensibleType
|
||||
) {
|
||||
any(FrameworkModeMetadataExtractor meta)
|
||||
.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
|
||||
_, extensibleType) and
|
||||
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _)
|
||||
}
|
||||
|
||||
/*
|
||||
* EndpointCharacteristic classes that are specific to Automodel for Java.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an is-style boolean method is unexploitable even if it is a sink.
|
||||
* A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks,
|
||||
* and its return value should not be considered a source.
|
||||
*
|
||||
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
|
||||
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
|
||||
@@ -313,45 +402,70 @@ class FrameworkModeMetadataExtractor extends string {
|
||||
*
|
||||
* TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks
|
||||
*/
|
||||
private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
|
||||
private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
|
||||
{
|
||||
UnexploitableIsCharacteristic() { this = "unexploitable (is-style boolean method)" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
not FrameworkCandidatesImpl::isSink(e, _, _) and
|
||||
e.getEnclosingCallable().getName().matches("is%") and
|
||||
e.getEnclosingCallable().getReturnType() instanceof BooleanType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an existence-checking boolean method is unexploitable even if it is a
|
||||
* sink.
|
||||
*
|
||||
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
|
||||
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
|
||||
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
|
||||
*/
|
||||
private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
|
||||
UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
not FrameworkCandidatesImpl::isSink(e, _, _) and
|
||||
exists(Callable callable |
|
||||
callable = e.getEnclosingCallable() and
|
||||
callable.getName().toLowerCase() = ["exists", "notexists"] and
|
||||
callable.getReturnType() instanceof BooleanType
|
||||
e.getCallable().getName().matches("is%") and
|
||||
e.getCallable().getReturnType() instanceof BooleanType and
|
||||
(
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not FrameworkCandidatesImpl::isSink(e, _, _)
|
||||
or
|
||||
e.getExtensibleType() = "sourceModel" and
|
||||
not FrameworkCandidatesImpl::isSource(e, _, _) and
|
||||
e.getMaDOutput() = "ReturnValue"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an endpoint is an argument to an exception, which is not a sink.
|
||||
* A negative characteristic that indicates that parameters of an existence-checking boolean method should not be
|
||||
* considered sinks, and its return value should not be considered a source.
|
||||
*
|
||||
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
|
||||
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
|
||||
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
|
||||
*/
|
||||
private class ExceptionCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
|
||||
private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
|
||||
{
|
||||
UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
exists(Callable callable |
|
||||
callable = e.getCallable() and
|
||||
callable.getName().toLowerCase() = ["exists", "notexists"] and
|
||||
callable.getReturnType() instanceof BooleanType
|
||||
|
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not FrameworkCandidatesImpl::isSink(e, _, _)
|
||||
or
|
||||
e.getExtensibleType() = "sourceModel" and
|
||||
not FrameworkCandidatesImpl::isSource(e, _, _) and
|
||||
e.getMaDOutput() = "ReturnValue"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks,
|
||||
* and its return value should not be considered a source.
|
||||
*/
|
||||
private class ExceptionCharacteristic extends CharacteristicsImpl::NeitherSourceNorSinkCharacteristic
|
||||
{
|
||||
ExceptionCharacteristic() { this = "exception" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
e.getEnclosingCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable
|
||||
e.getCallable().getDeclaringType().getASupertype*() instanceof TypeThrowable and
|
||||
(
|
||||
e.getExtensibleType() = "sinkModel" and
|
||||
not FrameworkCandidatesImpl::isSink(e, _, _)
|
||||
or
|
||||
e.getExtensibleType() = "sourceModel" and
|
||||
not FrameworkCandidatesImpl::isSource(e, _, _) and
|
||||
e.getMaDOutput() = "ReturnValue"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +477,6 @@ private class NotAModelApi extends CharacteristicsImpl::UninterestingToModelChar
|
||||
NotAModelApi() { this = "not a model API" }
|
||||
|
||||
override predicate appliesToEndpoint(Endpoint e) {
|
||||
not e.getEnclosingCallable() instanceof ModelExclusions::ModelApi
|
||||
not e.getCallable() instanceof ModelExclusions::ModelApi
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,29 +16,12 @@ private import AutomodelFrameworkModeCharacteristics
|
||||
private import AutomodelJavaUtil
|
||||
|
||||
from
|
||||
Endpoint endpoint, FrameworkModeMetadataExtractor meta, DollarAtString package,
|
||||
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
|
||||
DollarAtString input, DollarAtString output, DollarAtString parameterName,
|
||||
DollarAtString alreadyAiModeled, DollarAtString extensibleType
|
||||
Endpoint endpoint, DollarAtString package, DollarAtString type, DollarAtString subtypes,
|
||||
DollarAtString name, DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString parameterName, DollarAtString alreadyAiModeled, DollarAtString extensibleType
|
||||
where
|
||||
endpoint.getExtensibleType() = extensibleType and
|
||||
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
|
||||
u.appliesToEndpoint(endpoint)
|
||||
) and
|
||||
CharacteristicsImpl::isSinkCandidate(endpoint, _) and
|
||||
// If a node is already a known sink for any of our existing ATM queries and is already modeled as a MaD sink, we
|
||||
// don't include it as a candidate. Otherwise, we might include it as a candidate for query A, but the model will
|
||||
// label it as a sink for one of the sink types of query B, for which it's already a known sink. This would result in
|
||||
// overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been
|
||||
// modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it.
|
||||
(
|
||||
not CharacteristicsImpl::isSink(endpoint, _, _) and alreadyAiModeled = ""
|
||||
or
|
||||
alreadyAiModeled.matches("%ai-%") and
|
||||
CharacteristicsImpl::isSink(endpoint, _, alreadyAiModeled)
|
||||
) and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName) and
|
||||
includeAutomodelCandidate(package, type, name, signature)
|
||||
isCandidate(endpoint, package, type, subtypes, name, signature, input, output, parameterName,
|
||||
extensibleType, alreadyAiModeled)
|
||||
select endpoint,
|
||||
"Related locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
|
||||
|
||||
@@ -14,29 +14,15 @@ private import AutomodelJavaUtil
|
||||
|
||||
from
|
||||
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence,
|
||||
DollarAtString message, FrameworkModeMetadataExtractor meta, DollarAtString package,
|
||||
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
|
||||
DollarAtString input, DollarAtString output, DollarAtString parameterName,
|
||||
DollarAtString extensibleType
|
||||
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
|
||||
DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString parameterName, DollarAtString extensibleType
|
||||
where
|
||||
endpoint.getExtensibleType() = extensibleType and
|
||||
characteristic.appliesToEndpoint(endpoint) and
|
||||
confidence >= SharedCharacteristics::highConfidence() and
|
||||
characteristic.hasImplications(any(NegativeSinkType negative), true, confidence) and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName) and
|
||||
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
|
||||
// treated by the actual query as a sanitizer, since the final logic is something like
|
||||
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
|
||||
// they're ambiguous and might confuse the model, so we explicitly exclude all known sinks from the negative examples.
|
||||
not exists(EndpointCharacteristic characteristic2, float confidence2, SinkType positiveType |
|
||||
not positiveType instanceof NegativeSinkType and
|
||||
characteristic2.appliesToEndpoint(endpoint) and
|
||||
confidence2 >= SharedCharacteristics::maximalConfidence() and
|
||||
characteristic2.hasImplications(positiveType, true, confidence2)
|
||||
) and
|
||||
message = characteristic
|
||||
isNegativeExample(endpoint, characteristic, confidence, package, type, subtypes, name, signature,
|
||||
input, output, parameterName, extensibleType)
|
||||
select endpoint,
|
||||
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
characteristic + "\nrelated locations: $@, $@." +
|
||||
"\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
|
||||
package, "package", //
|
||||
|
||||
@@ -13,15 +13,12 @@ private import AutomodelEndpointTypes
|
||||
private import AutomodelJavaUtil
|
||||
|
||||
from
|
||||
Endpoint endpoint, EndpointType endpointType, FrameworkModeMetadataExtractor meta,
|
||||
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
|
||||
DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString parameterName, DollarAtString extensibleType
|
||||
Endpoint endpoint, EndpointType endpointType, DollarAtString package, DollarAtString type,
|
||||
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input,
|
||||
DollarAtString output, DollarAtString parameterName, DollarAtString extensibleType
|
||||
where
|
||||
endpoint.getExtensibleType() = extensibleType and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName) and
|
||||
// Extract positive examples of sinks belonging to the existing ATM query configurations.
|
||||
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _)
|
||||
isPositiveExample(endpoint, endpointType, package, type, subtypes, name, signature, input, output,
|
||||
parameterName, extensibleType)
|
||||
select endpoint,
|
||||
endpointType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
|
||||
|
||||
@@ -82,3 +82,43 @@ predicate includeAutomodelCandidate(string package, string type, string name, st
|
||||
not automodelCandidateFilter(_, _, _, _) or
|
||||
automodelCandidateFilter(package, type, name, signature)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given program element corresponds to a piece of source code,
|
||||
* that is, it is not compiler-generated.
|
||||
*
|
||||
* Note: This is a stricter check than `Element::fromSource`, which simply
|
||||
* checks whether the element is in a source file as opposed to a JAR file.
|
||||
* There can be compiler-generated elements in source files (especially for
|
||||
* Kotlin), which we also want to exclude.
|
||||
*/
|
||||
predicate isFromSource(Element e) {
|
||||
// from a source file (not a JAR)
|
||||
e.fromSource() and
|
||||
// not explicitly marked as compiler-generated
|
||||
not e.isCompilerGenerated() and
|
||||
// does not have a dummy location
|
||||
not e.hasLocationInfo(_, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint cannot flow through the given type (because it is a numeric
|
||||
* type or some other type with a fixed set of values).
|
||||
*/
|
||||
predicate isUnexploitableType(Type tp) {
|
||||
tp instanceof PrimitiveType or
|
||||
tp instanceof BoxedType or
|
||||
tp instanceof NumberType or
|
||||
tp instanceof VoidType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given method can be overridden, that is, it is not final,
|
||||
* static, or private.
|
||||
*/
|
||||
predicate isOverridable(Method m) {
|
||||
not m.getDeclaringType().isFinal() and
|
||||
not m.isFinal() and
|
||||
not m.isStatic() and
|
||||
not m.isPrivate()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,17 @@ signature module CandidateSig {
|
||||
* An endpoint is a potential candidate for modeling. This will typically be bound to the language's
|
||||
* DataFlow node class, or a subtype thereof.
|
||||
*/
|
||||
class Endpoint;
|
||||
class Endpoint {
|
||||
/**
|
||||
* Gets the kind of this endpoint, either "sourceModel" or "sinkModel".
|
||||
*/
|
||||
string getExtensibleType();
|
||||
|
||||
/**
|
||||
* Gets a string representation of this endpoint.
|
||||
*/
|
||||
string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A related location for an endpoint. This will typically be bound to the supertype of all AST nodes (eg., `Top`).
|
||||
@@ -31,14 +41,19 @@ signature module CandidateSig {
|
||||
class RelatedLocationType;
|
||||
|
||||
/**
|
||||
* A class kind for an endpoint.
|
||||
* An endpoint type considered by this specification.
|
||||
*/
|
||||
class EndpointType extends string;
|
||||
|
||||
/**
|
||||
* An EndpointType that denotes the absence of any sink.
|
||||
* A sink endpoint type considered by this specification.
|
||||
*/
|
||||
class NegativeEndpointType extends EndpointType;
|
||||
class SinkType extends EndpointType;
|
||||
|
||||
/**
|
||||
* A source endpoint type considered by this specification.
|
||||
*/
|
||||
class SourceType extends EndpointType;
|
||||
|
||||
/**
|
||||
* Gets the endpoint as a location.
|
||||
@@ -103,7 +118,7 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `endpoint` is modeled as `endpointType` (endpoint type must not be negative).
|
||||
* Holds if `endpoint` is modeled as `endpointType`.
|
||||
*/
|
||||
predicate isKnownAs(
|
||||
Candidate::Endpoint endpoint, Candidate::EndpointType endpointType,
|
||||
@@ -111,19 +126,31 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
) {
|
||||
// If the list of characteristics includes positive indicators with maximal confidence for this class, then it's a
|
||||
// known sink for the class.
|
||||
not endpointType instanceof Candidate::NegativeEndpointType and
|
||||
characteristic.appliesToEndpoint(endpoint) and
|
||||
characteristic.hasImplications(endpointType, true, maximalConfidence())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the candidate sink `candidateSink` should be considered as a possible sink of type `sinkType`, and
|
||||
* classified by the ML model. A candidate sink is a node that cannot be excluded from `sinkType` based on its
|
||||
* characteristics.
|
||||
* Gets a potential type of this endpoint to make sure that sources are
|
||||
* associated with source types and sinks with sink types.
|
||||
*/
|
||||
predicate isSinkCandidate(Candidate::Endpoint candidateSink, Candidate::EndpointType sinkType) {
|
||||
not sinkType instanceof Candidate::NegativeEndpointType and
|
||||
not exists(getAReasonSinkExcluded(candidateSink, sinkType))
|
||||
Candidate::EndpointType getAPotentialType(Candidate::Endpoint endpoint) {
|
||||
endpoint.getExtensibleType() = "sourceModel" and
|
||||
result instanceof Candidate::SourceType
|
||||
or
|
||||
endpoint.getExtensibleType() = "sinkModel" and
|
||||
result instanceof Candidate::SinkType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the given `endpoint` should be considered as a candidate for type `endpointType`,
|
||||
* and classified by the ML model.
|
||||
*
|
||||
* A candidate is an endpoint that cannot be excluded from `endpointType` based on its characteristics.
|
||||
*/
|
||||
predicate isCandidate(Candidate::Endpoint endpoint, Candidate::EndpointType endpointType) {
|
||||
endpointType = getAPotentialType(endpoint) and
|
||||
not exists(getAnExcludingCharacteristic(endpoint, endpointType))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,27 +166,16 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of characteristics that cause `candidateSink` to be excluded as an effective sink for a given sink
|
||||
* type.
|
||||
* Gets a characteristics that disbar `endpoint` from being a candidate for `endpointType`
|
||||
* with at least medium confidence.
|
||||
*/
|
||||
EndpointCharacteristic getAReasonSinkExcluded(
|
||||
Candidate::Endpoint candidateSink, Candidate::EndpointType sinkType
|
||||
EndpointCharacteristic getAnExcludingCharacteristic(
|
||||
Candidate::Endpoint endpoint, Candidate::EndpointType endpointType
|
||||
) {
|
||||
// An endpoint is a sink candidate if none of its characteristics give much indication whether or not it is a sink.
|
||||
not sinkType instanceof Candidate::NegativeEndpointType and
|
||||
result.appliesToEndpoint(candidateSink) and
|
||||
(
|
||||
// Exclude endpoints that have a characteristic that implies they're not sinks for _any_ sink type.
|
||||
exists(float confidence |
|
||||
confidence >= mediumConfidence() and
|
||||
result.hasImplications(any(Candidate::NegativeEndpointType t), true, confidence)
|
||||
)
|
||||
or
|
||||
// Exclude endpoints that have a characteristic that implies they're not sinks for _this particular_ sink type.
|
||||
exists(float confidence |
|
||||
confidence >= mediumConfidence() and
|
||||
result.hasImplications(sinkType, false, confidence)
|
||||
)
|
||||
result.appliesToEndpoint(endpoint) and
|
||||
exists(float confidence |
|
||||
confidence >= mediumConfidence() and
|
||||
result.hasImplications(endpointType, false, confidence)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -250,12 +266,46 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
override predicate hasImplications(
|
||||
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointType instanceof Candidate::NegativeEndpointType and
|
||||
isPositiveIndicator = true and
|
||||
endpointType instanceof Candidate::SinkType and
|
||||
isPositiveIndicator = false and
|
||||
confidence = highConfidence()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A high-confidence characteristic that indicates that an endpoint is not a source of any type. These endpoints can be
|
||||
* used as negative samples for training or for a few-shot prompt.
|
||||
*/
|
||||
abstract class NotASourceCharacteristic extends EndpointCharacteristic {
|
||||
bindingset[this]
|
||||
NotASourceCharacteristic() { any() }
|
||||
|
||||
override predicate hasImplications(
|
||||
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointType instanceof Candidate::SourceType and
|
||||
isPositiveIndicator = false and
|
||||
confidence = highConfidence()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A high-confidence characteristic that indicates that an endpoint is neither a source nor a sink of any type.
|
||||
*/
|
||||
abstract class NeitherSourceNorSinkCharacteristic extends NotASinkCharacteristic,
|
||||
NotASourceCharacteristic
|
||||
{
|
||||
bindingset[this]
|
||||
NeitherSourceNorSinkCharacteristic() { any() }
|
||||
|
||||
final override predicate hasImplications(
|
||||
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
NotASinkCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence) or
|
||||
NotASourceCharacteristic.super.hasImplications(endpointType, isPositiveIndicator, confidence)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A medium-confidence characteristic that indicates that an endpoint is unlikely to be a sink of any type. These
|
||||
* endpoints can be excluded from scoring at inference time, both to save time and to avoid false positives. They should
|
||||
@@ -269,8 +319,8 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
override predicate hasImplications(
|
||||
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointType instanceof Candidate::NegativeEndpointType and
|
||||
isPositiveIndicator = true and
|
||||
endpointType instanceof Candidate::SinkType and
|
||||
isPositiveIndicator = false and
|
||||
confidence = mediumConfidence()
|
||||
}
|
||||
}
|
||||
@@ -290,8 +340,8 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
override predicate hasImplications(
|
||||
Candidate::EndpointType endpointType, boolean isPositiveIndicator, float confidence
|
||||
) {
|
||||
endpointType instanceof Candidate::NegativeEndpointType and
|
||||
isPositiveIndicator = true and
|
||||
endpointType instanceof Candidate::SinkType and
|
||||
isPositiveIndicator = false and
|
||||
confidence = mediumConfidence()
|
||||
}
|
||||
}
|
||||
@@ -344,17 +394,16 @@ module SharedCharacteristics<CandidateSig Candidate> {
|
||||
/**
|
||||
* A negative characteristic that indicates that an endpoint was manually modeled as a neutral model.
|
||||
*/
|
||||
private class NeutralModelCharacteristic extends NotASinkCharacteristic {
|
||||
private class NeutralModelCharacteristic extends NeitherSourceNorSinkCharacteristic {
|
||||
NeutralModelCharacteristic() { this = "known non-sink" }
|
||||
|
||||
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isNeutral(e) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A negative characteristic that indicates that an endpoint is not part of the source code for the project being
|
||||
* analyzed.
|
||||
* A negative characteristic that indicates that an endpoint is a sanitizer, and thus not a source.
|
||||
*/
|
||||
private class IsSanitizerCharacteristic extends NotASinkCharacteristic {
|
||||
private class IsSanitizerCharacteristic extends NotASourceCharacteristic {
|
||||
IsSanitizerCharacteristic() { this = "known sanitizer" }
|
||||
|
||||
override predicate appliesToEndpoint(Candidate::Endpoint e) { Candidate::isSanitizer(e, _) }
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* An automodel extraction mode instantiates this interface to define how to access
|
||||
* the callable that's associated with an endpoint.
|
||||
*/
|
||||
signature module GetCallableSig {
|
||||
/**
|
||||
* A callable is the definition of a method, function, etc. - something that can be called.
|
||||
*/
|
||||
class Callable;
|
||||
|
||||
/**
|
||||
* An endpoint is a potential candidate for modeling. This will typically be bound to the language's
|
||||
* DataFlow node class, or a subtype thereof.
|
||||
*/
|
||||
class Endpoint;
|
||||
|
||||
/**
|
||||
* Gets the callable that's associated with the given endpoint.
|
||||
*/
|
||||
Callable getCallable(Endpoint endpoint);
|
||||
}
|
||||
@@ -1,3 +1,15 @@
|
||||
## 0.0.13
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.0.12
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.0.11
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.0.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -65,7 +65,7 @@ A significant part of the behavior of extraction queries is implemented in share
|
||||
|
||||
## Packaging
|
||||
|
||||
Automodel extraction queries come as a dedicated package. See [qlpack.yml](https://github.com/github/codeql/blob/main/java/ql/automodel/src/qlpack.yml). The [publish.sh](https://github.com/github/codeql/blob/main/java/ql/automodel/publish.sh) script is responsible for publishing a new version to the [package registry](https://github.com/orgs/codeql/packages/container/package/java-automodel-queries).
|
||||
Automodel extraction queries come as a dedicated package. See [qlpack.yml](https://github.com/github/codeql/blob/main/java/ql/automodel/src/qlpack.yml). The [publish.sh](https://github.com/github/codeql/blob/main/java/ql/automodel/publish.sh) script is responsible for publishing a new version to the [package registry](https://github.com/orgs/codeql/packages/container/package/java-automodel-queries). **The extraction queries are functionally coupled with other automodel components. Only publish the query pack as part of the automodel release process.**
|
||||
|
||||
### Backwards Compatibility
|
||||
|
||||
|
||||
3
java/ql/automodel/src/change-notes/released/0.0.11.md
Normal file
3
java/ql/automodel/src/change-notes/released/0.0.11.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.11
|
||||
|
||||
No user-facing changes.
|
||||
3
java/ql/automodel/src/change-notes/released/0.0.12.md
Normal file
3
java/ql/automodel/src/change-notes/released/0.0.12.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.12
|
||||
|
||||
No user-facing changes.
|
||||
3
java/ql/automodel/src/change-notes/released/0.0.13.md
Normal file
3
java/ql/automodel/src/change-notes/released/0.0.13.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.0.13
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.10
|
||||
lastReleaseVersion: 0.0.13
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/java-automodel-queries
|
||||
version: 0.0.10
|
||||
version: 0.0.13
|
||||
groups:
|
||||
- java
|
||||
- automodel
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
| PluginImpl.java:5:27:5:37 | name | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:27:5:37 | name | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| PluginImpl.java:5:40:5:51 | value | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | PluginImpl.java:5:40:5:51 | value | CallContext | hudson/Plugin.java:5:5:5:31 | /** Configure method doc */ | MethodDoc | hudson/Plugin.java:3:1:3:17 | /** Plugin doc */ | ClassDoc | file://hudson:1:1:1:1 | hudson | package | file://Plugin:1:1:1:1 | Plugin | type | file://true:1:1:1:1 | true | subtypes | file://configure:1:1:1:1 | configure | name | file://(String,String):1:1:1:1 | (String,String) | signature | file://:1:1:1:1 | | input | file://Parameter[1]:1:1:1:1 | Parameter[1] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:19:3:19:11 | reference | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:19:3:19:24 | set(...) | CallContext | Test.java:19:3:19:11 | reference | MethodDoc | Test.java:19:3:19:11 | reference | ClassDoc | file://java.util.concurrent.atomic:1:1:1:1 | java.util.concurrent.atomic | package | file://AtomicReference:1:1:1:1 | AtomicReference | type | file://false:1:1:1:1 | false | subtypes | file://set:1:1:1:1 | set | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:24:3:24:10 | supplier | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:10 | supplier | MethodDoc | Test.java:24:3:24:10 | supplier | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:24:3:24:16 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:24:3:24:16 | get(...) | CallContext | Test.java:24:3:24:16 | get(...) | MethodDoc | Test.java:24:3:24:16 | get(...) | ClassDoc | file://java.util.function:1:1:1:1 | java.util.function | package | file://Supplier:1:1:1:1 | Supplier | type | file://true:1:1:1:1 | true | subtypes | file://get:1:1:1:1 | get | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:28:3:32:3 | copy(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:28:3:32:3 | copy(...) | MethodDoc | Test.java:28:3:32:3 | copy(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:36:10:38:3 | newInputStream(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:36:10:38:3 | newInputStream(...) | MethodDoc | Test.java:36:10:38:3 | newInputStream(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:37:4:37:11 | openPath | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:43:4:43:22 | get(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:43:4:43:22 | get(...) | CallContext | Test.java:43:4:43:22 | get(...) | MethodDoc | Test.java:43:4:43:22 | get(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Paths:1:1:1:1 | Paths | type | file://false:1:1:1:1 | false | subtypes | file://get:1:1:1:1 | get | name | file://(String,String[]):1:1:1:1 | (String,String[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:54:3:59:3 | walk(...) | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:56:4:56:4 | o | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:54:3:59:3 | walk(...) | MethodDoc | Test.java:54:3:59:3 | walk(...) | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://true:1:1:1:1 | true | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:63:3:63:3 | c | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:3 | c | MethodDoc | Test.java:63:3:63:3 | c | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:68:30:68:47 | writer | Related locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:68:30:68:47 | writer | CallContext | Test.java:68:30:68:47 | writer | MethodDoc | Test.java:68:30:68:47 | writer | ClassDoc | file://java.lang:1:1:1:1 | java.lang | package | file://Throwable:1:1:1:1 | Throwable | type | file://true:1:1:1:1 | true | subtypes | file://printStackTrace:1:1:1:1 | printStackTrace | name | file://(PrintWriter):1:1:1:1 | (PrintWriter) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://false:1:1:1:1 | false | isVarargsArray | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelApplicationModeExtractCandidates.ql
|
||||
@@ -1,3 +0,0 @@
|
||||
| Test.java:48:10:50:3 | compareTo(...) | known sanitizer\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:48:10:50:3 | compareTo(...) | MethodDoc | Test.java:48:10:50:3 | compareTo(...) | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| Test.java:49:4:49:5 | f2 | known non-sink\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:48:10:50:3 | compareTo(...) | CallContext | Test.java:49:4:49:5 | f2 | MethodDoc | Test.java:49:4:49:5 | f2 | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:55:4:55:4 | p | taint step\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:54:3:59:3 | walk(...) | CallContext | Test.java:55:4:55:4 | p | MethodDoc | Test.java:55:4:55:4 | p | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://walk:1:1:1:1 | walk | name | file://(Path,FileVisitOption[]):1:1:1:1 | (Path,FileVisitOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelApplicationModeExtractNegativeExamples.ql
|
||||
@@ -1,4 +0,0 @@
|
||||
| Test.java:29:4:29:9 | source | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:29:4:29:9 | source | MethodDoc | Test.java:29:4:29:9 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:30:4:30:9 | target | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:28:3:32:3 | copy(...) | CallContext | Test.java:30:4:30:9 | target | MethodDoc | Test.java:30:4:30:9 | target | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,Path,CopyOption[]):1:1:1:1 | (Path,Path,CopyOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:37:4:37:11 | openPath | path-injection\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:36:10:38:3 | newInputStream(...) | CallContext | Test.java:37:4:37:11 | openPath | MethodDoc | Test.java:37:4:37:11 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://false:1:1:1:1 | false | isVarargsArray | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| Test.java:63:3:63:20 | getInputStream(...) | remote\nrelated locations: $@, $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | Test.java:63:3:63:20 | getInputStream(...) | CallContext | Test.java:63:3:63:20 | getInputStream(...) | MethodDoc | Test.java:63:3:63:20 | getInputStream(...) | ClassDoc | file://java.net:1:1:1:1 | java.net | package | file://URLConnection:1:1:1:1 | URLConnection | type | file://true:1:1:1:1 | true | subtypes | file://getInputStream:1:1:1:1 | getInputStream | name | file://():1:1:1:1 | () | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://false:1:1:1:1 | false | isVarargsArray | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelApplicationModeExtractPositiveExamples.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,35 @@
|
||||
import java
|
||||
import AutomodelApplicationModeCharacteristics as Characteristics
|
||||
import AutomodelExtractionTests
|
||||
|
||||
module TestHelper implements TestHelperSig<Characteristics::ApplicationCandidatesImpl> {
|
||||
Location getEndpointLocation(Characteristics::Endpoint endpoint) {
|
||||
result = endpoint.asTop().getLocation()
|
||||
}
|
||||
|
||||
predicate isCandidate(
|
||||
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
) {
|
||||
Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _,
|
||||
extensibleType, _)
|
||||
}
|
||||
|
||||
predicate isPositiveExample(
|
||||
Characteristics::Endpoint endpoint, string endpointType, string name, string signature,
|
||||
string input, string output, string extensibleType
|
||||
) {
|
||||
Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input,
|
||||
output, _, extensibleType)
|
||||
}
|
||||
|
||||
predicate isNegativeExample(
|
||||
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
) {
|
||||
Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _,
|
||||
extensibleType)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<Extraction<Characteristics::ApplicationCandidatesImpl, TestHelper>>
|
||||
@@ -2,7 +2,7 @@ import hudson.Plugin;
|
||||
|
||||
public class PluginImpl extends Plugin {
|
||||
@Override
|
||||
public void configure(String name, String value) {
|
||||
public void configure(String name, String value) { // $ sourceModelCandidate=configure(String,String):Parameter[0] sourceModelCandidate=configure(String,String):Parameter[1]
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,56 +16,59 @@ import java.util.concurrent.FutureTask;
|
||||
class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
AtomicReference<String> reference = new AtomicReference<>(); // uninteresting (parameterless constructor)
|
||||
reference.set(args[0]); // arg[0] is not a candidate (modeled as value flow step)
|
||||
// ^^^^^^ Argument[this] is a candidate
|
||||
reference.set( // $ sinkModelCandidate=set(Object):Argument[this]
|
||||
args[0] // $ negativeSinkExample=set(Object):Argument[0] // modeled as a flow step
|
||||
); // $ negativeSourceExample=set(Object):ReturnValue // return type is void
|
||||
}
|
||||
|
||||
public static void callSupplier(Supplier<String> supplier) {
|
||||
supplier.get(); // Argument[this] is a sink candidate; the call is a source candidate
|
||||
supplier.get(); // $ sourceModelCandidate=get():ReturnValue sinkModelCandidate=get():Argument[this]
|
||||
}
|
||||
|
||||
public static void copyFiles(Path source, Path target, CopyOption option) throws Exception {
|
||||
Files.copy( // the call is a source candidate
|
||||
source, // positive example (known sink)
|
||||
target, // positive example (known sink)
|
||||
Files.copy(
|
||||
source, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[0](path-injection)
|
||||
target, // $ positiveSinkExample=copy(Path,Path,CopyOption[]):Argument[1](path-injection)
|
||||
option // no candidate (not modeled, but source and target are modeled)
|
||||
);
|
||||
); // $ sourceModelCandidate=copy(Path,Path,CopyOption[]):ReturnValue
|
||||
}
|
||||
|
||||
public static InputStream getInputStream(Path openPath) throws Exception {
|
||||
return Files.newInputStream( // the call is a source candidate
|
||||
openPath // positive example (known sink), candidate ("only" ai-modeled, and useful as a candidate in regression testing)
|
||||
);
|
||||
return Files.newInputStream(
|
||||
openPath // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) // sink candidate because "only" ai-modeled, and useful as a candidate in regression testing
|
||||
); // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue
|
||||
}
|
||||
|
||||
public static InputStream getInputStream(String openPath) throws Exception {
|
||||
return Test.getInputStream( // the call is not a source candidate (argument to local call)
|
||||
Paths.get(openPath) // no sink candidate (argument to local call); the call is a source candidate
|
||||
Paths.get(
|
||||
openPath // $ negativeSinkExample=get(String,String[]):Argument[0] // modeled as a flow step
|
||||
) // $ sourceModelCandidate=get(String,String[]):ReturnValue
|
||||
);
|
||||
}
|
||||
|
||||
public static int compareFiles(File f1, File f2) {
|
||||
return f1.compareTo( // compareTo call is a known sanitizer
|
||||
f2 // negative sink example (modeled as not a sink)
|
||||
); // the call is a negative source candidate (sanitizer)
|
||||
return f1.compareTo( // $ negativeSinkExample=compareTo(File):Argument[this]
|
||||
f2 // $ negativeSinkExample=compareTo(File):Argument[0] // modeled as not a sink
|
||||
); // $ negativeSourceExample=compareTo(File):ReturnValue // return type is int
|
||||
}
|
||||
|
||||
public static void FilesWalkExample(Path p, FileVisitOption o) throws Exception {
|
||||
Files.walk( // the call is a source candidate
|
||||
p, // negative example (modeled as a taint step)
|
||||
o, // the implicit varargs array is a candidate
|
||||
Files.walk(
|
||||
p, // $ negativeSinkExample=walk(Path,FileVisitOption[]):Argument[0] // modeled as a flow step
|
||||
o, // the implicit varargs array is a candidate, annotated on the last line of the call
|
||||
o // not a candidate (only the first arg corresponding to a varargs array
|
||||
// is extracted)
|
||||
);
|
||||
); // $ sourceModelCandidate=walk(Path,FileVisitOption[]):ReturnValue sinkModelCandidate=walk(Path,FileVisitOption[]):Argument[1]
|
||||
}
|
||||
|
||||
public static void WebSocketExample(URLConnection c) throws Exception {
|
||||
c.getInputStream(); // the call is a source example, c is a sink candidate
|
||||
c.getInputStream(); // $ sinkModelCandidate=getInputStream():Argument[this] positiveSourceExample=getInputStream():ReturnValue(remote) // not a source candidate (manual modeling)
|
||||
}
|
||||
}
|
||||
|
||||
class OverrideTest extends Exception {
|
||||
public void printStackTrace(PrintWriter writer) { // writer is a source candidate because it overrides an existing method
|
||||
public void printStackTrace(PrintWriter writer) { // $ sourceModelCandidate=printStackTrace(PrintWriter):Parameter[0]
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,3 +83,21 @@ class TaskUtils {
|
||||
return ft;
|
||||
}
|
||||
}
|
||||
|
||||
class MoreTests {
|
||||
public static void FilesListExample(Path p) throws Exception {
|
||||
Files.list(
|
||||
Files.createDirectories(
|
||||
p // $ positiveSinkExample=createDirectories(Path,FileAttribute[]):Argument[0](path-injection)
|
||||
) // $ sourceModelCandidate=createDirectories(Path,FileAttribute[]):ReturnValue negativeSinkExample=list(Path):Argument[0] // modeled as a flow step
|
||||
); // $ sourceModelCandidate=list(Path):ReturnValue
|
||||
|
||||
Files.delete(
|
||||
p // $ sinkModelCandidate=delete(Path):Argument[0] positiveSinkExample=delete(Path):Argument[0](path-injection)
|
||||
); // $ negativeSourceExample=delete(Path):ReturnValue // return type is void
|
||||
|
||||
Files.deleteIfExists(
|
||||
p // $ sinkModelCandidate=deleteIfExists(Path):Argument[0] positiveSinkExample=deleteIfExists(Path):Argument[0](path-injection)
|
||||
); // $ negativeSourceExample=deleteIfExists(Path):ReturnValue // return type is boolean
|
||||
}
|
||||
}
|
||||
77
java/ql/automodel/test/AutomodelExtractionTests.qll
Normal file
77
java/ql/automodel/test/AutomodelExtractionTests.qll
Normal file
@@ -0,0 +1,77 @@
|
||||
import java
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
import AutomodelSharedCharacteristics
|
||||
|
||||
signature module TestHelperSig<CandidateSig Candidate> {
|
||||
Location getEndpointLocation(Candidate::Endpoint e);
|
||||
|
||||
predicate isCandidate(
|
||||
Candidate::Endpoint e, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
);
|
||||
|
||||
predicate isPositiveExample(
|
||||
Candidate::Endpoint e, string endpointType, string name, string signature, string input,
|
||||
string output, string extensibleType
|
||||
);
|
||||
|
||||
predicate isNegativeExample(
|
||||
Candidate::Endpoint e, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
);
|
||||
}
|
||||
|
||||
module Extraction<CandidateSig Candidate, TestHelperSig<Candidate> TestHelper> implements TestSig {
|
||||
string getARelevantTag() {
|
||||
result in [
|
||||
"sourceModelCandidate", "sinkModelCandidate", // a candidate source/sink
|
||||
"positiveSourceExample", "positiveSinkExample", // a known source/sink
|
||||
"negativeSourceExample", "negativeSinkExample" // a known non-source/non-sink
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* If `extensibleType` is `sourceModel` then the result is `ifSource`, if it
|
||||
* is `sinkModel` then the result is `ifSink`.
|
||||
*/
|
||||
bindingset[extensibleType, ifSource, ifSink]
|
||||
private string ifSource(string extensibleType, string ifSource, string ifSink) {
|
||||
extensibleType = "sourceModel" and result = ifSource
|
||||
or
|
||||
extensibleType = "sinkModel" and result = ifSink
|
||||
}
|
||||
|
||||
additional predicate selectEndpoint(
|
||||
Candidate::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType, string tag, string suffix
|
||||
) {
|
||||
TestHelper::isCandidate(endpoint, name, signature, input, output, extensibleType) and
|
||||
tag = ifSource(extensibleType, "sourceModelCandidate", "sinkModelCandidate") and
|
||||
suffix = ""
|
||||
or
|
||||
TestHelper::isNegativeExample(endpoint, name, signature, input, output, extensibleType) and
|
||||
tag = "negative" + ifSource(extensibleType, "Source", "Sink") + "Example" and
|
||||
suffix = ""
|
||||
or
|
||||
exists(string endpointType |
|
||||
TestHelper::isPositiveExample(endpoint, endpointType, name, signature, input, output,
|
||||
extensibleType) and
|
||||
tag = "positive" + ifSource(extensibleType, "Source", "Sink") + "Example" and
|
||||
suffix = "(" + endpointType + ")"
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(
|
||||
Candidate::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType, string suffix
|
||||
|
|
||||
selectEndpoint(endpoint, name, signature, input, output, extensibleType, tag, suffix)
|
||||
|
|
||||
TestHelper::getEndpointLocation(endpoint) = location and
|
||||
endpoint.toString() = element and
|
||||
// for source models only the output is relevant, and vice versa for sink models
|
||||
value = name + signature + ":" + ifSource(extensibleType, output, input) + suffix
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | MethodDoc | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | MethodDoc | com/github/codeql/test/PublicClass.java:4:15:4:19 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:4:21:4:30 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:8:34:8:43 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | MethodDoc | com/github/codeql/test/PublicClass.java:13:18:13:31 | nonPublicStuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | MethodDoc | com/github/codeql/test/PublicClass.java:13:33:13:42 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://nonPublicStuff:1:1:1:1 | nonPublicStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | MethodDoc | com/github/codeql/test/PublicClass.java:22:10:22:20 | PublicClass | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicClass.java:22:22:22:33 | input | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | MethodDoc | com/github/codeql/test/PublicClass.java:22:22:22:33 | input | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicClass:1:1:1:1 | PublicClass | type | file://true:1:1:1:1 | true | subtypes | file://PublicClass:1:1:1:1 | PublicClass | name | file://(Object):1:1:1:1 | (Object) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://input:1:1:1:1 | input | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | MethodDoc | com/github/codeql/test/PublicInterface.java:4:16:4:20 | stuff | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:4:22:4:31 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://true:1:1:1:1 | true | subtypes | file://stuff:1:1:1:1 | stuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | MethodDoc | com/github/codeql/test/PublicInterface.java:6:36:6:45 | arg | ClassDoc | file://com.github.codeql.test:1:1:1:1 | com.github.codeql.test | package | file://PublicInterface:1:1:1:1 | PublicInterface | type | file://false:1:1:1:1 | false | subtypes | file://staticStuff:1:1:1:1 | staticStuff | name | file://(String):1:1:1:1 | (String) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://arg:1:1:1:1 | arg | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/io/File.java:10:20:10:34 | setLastModified | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:20:10:34 | setLastModified | MethodDoc | java/io/File.java:10:20:10:34 | setLastModified | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| java/io/File.java:10:20:10:34 | setLastModified | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:20:10:34 | setLastModified | MethodDoc | java/io/File.java:10:20:10:34 | setLastModified | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/io/File.java:10:36:10:44 | time | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:10:36:10:44 | time | MethodDoc | java/io/File.java:10:36:10:44 | time | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://setLastModified:1:1:1:1 | setLastModified | name | file://(long):1:1:1:1 | (long) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://time:1:1:1:1 | time | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| java/nio/file/Files.java:14:9:14:24 | out | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:14:9:14:24 | out | MethodDoc | java/nio/file/Files.java:14:9:14:24 | out | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://out:1:1:1:1 | out | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/nio/file/Files.java:24:31:24:44 | newInputStream | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:24:31:24:44 | newInputStream | MethodDoc | java/nio/file/Files.java:24:31:24:44 | newInputStream | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://:1:1:1:1 | | input | file://ReturnValue:1:1:1:1 | ReturnValue | output | file://:1:1:1:1 | | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| java/nio/file/Files.java:25:9:25:21 | openPath | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://openPath:1:1:1:1 | openPath | parameterName | file://ai-manual:1:1:1:1 | ai-manual | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/nio/file/Files.java:26:9:26:29 | options | Related locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:26:9:26:29 | options | MethodDoc | java/nio/file/Files.java:26:9:26:29 | options | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[1]:1:1:1:1 | Argument[1] | input | file://:1:1:1:1 | | output | file://options:1:1:1:1 | options | parameterName | file://:1:1:1:1 | | alreadyAiModeled | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelFrameworkModeExtractCandidates.ql
|
||||
@@ -1,4 +0,0 @@
|
||||
| java/io/File.java:4:16:4:24 | compareTo | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:4:16:4:24 | compareTo | MethodDoc | java/io/File.java:4:16:4:24 | compareTo | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://Parameter[this]:1:1:1:1 | Parameter[this] | output | file://this:1:1:1:1 | this | parameterName | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| java/io/File.java:4:16:4:24 | compareTo | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:4:16:4:24 | compareTo | MethodDoc | java/io/File.java:4:16:4:24 | compareTo | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[this]:1:1:1:1 | Argument[this] | input | file://:1:1:1:1 | | output | file://this:1:1:1:1 | this | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/io/File.java:5:9:5:21 | pathname | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:5:9:5:21 | pathname | MethodDoc | java/io/File.java:5:9:5:21 | pathname | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://:1:1:1:1 | | input | file://Parameter[0]:1:1:1:1 | Parameter[0] | output | file://pathname:1:1:1:1 | pathname | parameterName | file://sourceModel:1:1:1:1 | sourceModel | extensibleType |
|
||||
| java/io/File.java:5:9:5:21 | pathname | known non-sink\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/io/File.java:5:9:5:21 | pathname | MethodDoc | java/io/File.java:5:9:5:21 | pathname | ClassDoc | file://java.io:1:1:1:1 | java.io | package | file://File:1:1:1:1 | File | type | file://true:1:1:1:1 | true | subtypes | file://compareTo:1:1:1:1 | compareTo | name | file://(File):1:1:1:1 | (File) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://pathname:1:1:1:1 | pathname | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelFrameworkModeExtractNegativeExamples.ql
|
||||
@@ -1,2 +0,0 @@
|
||||
| java/nio/file/Files.java:13:9:13:19 | source | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:13:9:13:19 | source | MethodDoc | java/nio/file/Files.java:13:9:13:19 | source | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://copy:1:1:1:1 | copy | name | file://(Path,OutputStream):1:1:1:1 | (Path,OutputStream) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://source:1:1:1:1 | source | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
| java/nio/file/Files.java:25:9:25:21 | openPath | path-injection\nrelated locations: $@, $@.\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@. | java/nio/file/Files.java:25:9:25:21 | openPath | MethodDoc | java/nio/file/Files.java:25:9:25:21 | openPath | ClassDoc | file://java.nio.file:1:1:1:1 | java.nio.file | package | file://Files:1:1:1:1 | Files | type | file://false:1:1:1:1 | false | subtypes | file://newInputStream:1:1:1:1 | newInputStream | name | file://(Path,OpenOption[]):1:1:1:1 | (Path,OpenOption[]) | signature | file://Argument[0]:1:1:1:1 | Argument[0] | input | file://:1:1:1:1 | | output | file://openPath:1:1:1:1 | openPath | parameterName | file://sinkModel:1:1:1:1 | sinkModel | extensibleType |
|
||||
@@ -1 +0,0 @@
|
||||
AutomodelFrameworkModeExtractPositiveExamples.ql
|
||||
@@ -0,0 +1,2 @@
|
||||
testFailures
|
||||
failures
|
||||
@@ -0,0 +1,35 @@
|
||||
import java
|
||||
import AutomodelFrameworkModeCharacteristics as Characteristics
|
||||
import AutomodelExtractionTests
|
||||
|
||||
module TestHelper implements TestHelperSig<Characteristics::FrameworkCandidatesImpl> {
|
||||
Location getEndpointLocation(Characteristics::Endpoint endpoint) {
|
||||
result = endpoint.asTop().getLocation()
|
||||
}
|
||||
|
||||
predicate isCandidate(
|
||||
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
) {
|
||||
Characteristics::isCandidate(endpoint, _, _, _, name, signature, input, output, _,
|
||||
extensibleType, _)
|
||||
}
|
||||
|
||||
predicate isPositiveExample(
|
||||
Characteristics::Endpoint endpoint, string endpointType, string name, string signature,
|
||||
string input, string output, string extensibleType
|
||||
) {
|
||||
Characteristics::isPositiveExample(endpoint, endpointType, _, _, _, name, signature, input,
|
||||
output, _, extensibleType)
|
||||
}
|
||||
|
||||
predicate isNegativeExample(
|
||||
Characteristics::Endpoint endpoint, string name, string signature, string input, string output,
|
||||
string extensibleType
|
||||
) {
|
||||
Characteristics::isNegativeExample(endpoint, _, _, _, _, _, name, signature, input, output, _,
|
||||
extensibleType)
|
||||
}
|
||||
}
|
||||
|
||||
import MakeTest<Extraction<Characteristics::FrameworkCandidatesImpl, TestHelper>>
|
||||
@@ -1,25 +1,27 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
public class PublicClass {
|
||||
public void stuff(String arg) { // `arg` is a sink candidate, `this` is a candidate, `arg` is a source candidate (overrideable method)
|
||||
public void stuff(String arg) { // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // source candidates because it is an overrideable method
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
public static void staticStuff(String arg) { // `arg` is a candidate, `this` is not a candidate (static method), `arg` is not a source candidate (static methods can not be overloaded)
|
||||
public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // `arg` is not a source candidate (not overrideabe); `this` is not a candidate (static method)
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
// `arg` and `this` are candidates because the method is protected (may be called from downstream repositories). The return value is a candidate source for the same reason.
|
||||
protected void nonPublicStuff(String arg) {
|
||||
protected void nonPublicStuff(String arg) { // $ sinkModelCandidate=nonPublicStuff(String):Argument[this] sourceModelCandidate=nonPublicStuff(String):Parameter[this] sinkModelCandidate=nonPublicStuff(String):Argument[0] sourceModelCandidate=nonPublicStuff(String):Parameter[0]
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
// `arg` and `this are not candidates because the method is not public:
|
||||
void packagePrivateStuff(String arg) {
|
||||
void packagePrivateStuff(String arg) { // no candidates because the method is not public
|
||||
System.out.println(arg);
|
||||
}
|
||||
|
||||
public PublicClass(Object input) {
|
||||
// the `this` qualifier is not a candidate
|
||||
public PublicClass(Object input) { // $ sourceModelCandidate=PublicClass(Object):ReturnValue sinkModelCandidate=PublicClass(Object):Argument[0] // `this` is not a candidate because it is a constructor
|
||||
}
|
||||
|
||||
// `input` and `input` are source candidates, but not sink candidates (is-style method)
|
||||
public Boolean isIgnored(Object input) { // $ negativeSinkExample=isIgnored(Object):Argument[this] sourceModelCandidate=isIgnored(Object):Parameter[this] negativeSinkExample=isIgnored(Object):Argument[0] sourceModelCandidate=isIgnored(Object):Parameter[0]
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.github.codeql.test;
|
||||
|
||||
public interface PublicInterface {
|
||||
public int stuff(String arg); // `arg` is a candidate, `this` is a candidate, method stuff is _not_ a candidate source (primitive return type), `arg` is a source candidate (overridable method)
|
||||
public int stuff(String arg); // $ sinkModelCandidate=stuff(String):Argument[this] sourceModelCandidate=stuff(String):Parameter[this] sinkModelCandidate=stuff(String):Argument[0] sourceModelCandidate=stuff(String):Parameter[0] // result is _not_ a source candidate source (primitive return type)
|
||||
|
||||
public static void staticStuff(String arg) { // `arg` is a candidate, `this` is not a candidate (static method)
|
||||
public static void staticStuff(String arg) { // $ sinkModelCandidate=staticStuff(String):Argument[0] // not a source candidate (static method)
|
||||
System.out.println(arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package java.io;
|
||||
|
||||
public class File {
|
||||
public int compareTo( // `this` is a negative example - this is modeled as a neutral model
|
||||
File pathname // negative example - this is modeled as a neutral model
|
||||
public int compareTo( // $ negativeSinkExample=compareTo(File):Argument[this] negativeSourceExample=compareTo(File):Parameter[this] // modeled as neutral
|
||||
File pathname // $ negativeSinkExample=compareTo(File):Argument[0] negativeSourceExample=compareTo(File):Parameter[0] // modeled as neutral
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean setLastModified(long time) {
|
||||
public boolean setLastModified(long time) { // $ sinkModelCandidate=setLastModified(long):Argument[this] sourceModelCandidate=setLastModified(long):Parameter[this] // time is not a candidate (primitive type)
|
||||
return false;
|
||||
} // return value is not a source candidate because it's a primitive
|
||||
}
|
||||
|
||||
@@ -9,9 +9,10 @@ import java.io.OutputStream;
|
||||
import java.nio.file.OpenOption;
|
||||
|
||||
public class Files {
|
||||
public static void copy(
|
||||
Path source, // a positive example because a manual model exists
|
||||
OutputStream out /* a candidate. NB: may be worthwhile to implement the
|
||||
public static void copy( // method result is not a candidate source (void)
|
||||
Path source, // $ positiveSinkExample=copy(Path,OutputStream):Argument[0](path-injection) // manual model exists
|
||||
OutputStream out // $ sinkModelCandidate=copy(Path,OutputStream):Argument[1]
|
||||
/* NB: may be worthwhile to implement the
|
||||
same behavior as in application mode where out would not be a
|
||||
candidate because there already is a model for another parameter of
|
||||
the same method and we assume that methods are always modeled
|
||||
@@ -19,12 +20,12 @@ public class Files {
|
||||
*/
|
||||
) throws IOException {
|
||||
// ...
|
||||
} // method copy is a candidate source
|
||||
}
|
||||
|
||||
public static InputStream newInputStream(
|
||||
Path openPath ,// positive example (known sink), candidate (ai-modeled, and useful as a candidate in regression testing)
|
||||
OpenOption... options
|
||||
public static InputStream newInputStream( // $ sourceModelCandidate=newInputStream(Path,OpenOption[]):ReturnValue
|
||||
Path openPath, // $ positiveSinkExample=newInputStream(Path,OpenOption[]):Argument[0](path-injection) sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[0] // known sink, but still a candidate (ai-modeled, and useful as a candidate in regression testing)
|
||||
OpenOption... options // $ sinkModelCandidate=newInputStream(Path,OpenOption[]):Argument[1]
|
||||
) throws IOException {
|
||||
return new FileInputStream(openPath.toFile());
|
||||
} // method newInputStream is a candidate source
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ groups:
|
||||
dependencies:
|
||||
codeql/java-all: ${workspace}
|
||||
codeql/java-automodel-queries: ${workspace}
|
||||
codeql/java-tests: ${workspace}
|
||||
extractor: java
|
||||
tests: .
|
||||
warnOnImplicitThis: true
|
||||
@@ -0,0 +1,2 @@
|
||||
http://localhost:9428/releases/com/github/my/other/repo/test/otherreleasetest/1.0/otherreleasetest-1.0.jar
|
||||
http://localhost:9429/releases/com/github/hosted/in/other/repo/test/inotherrepo/1.0/inotherrepo-1.0.jar
|
||||
@@ -0,0 +1,28 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.mycompany.app</groupId>
|
||||
<artifactId>my-app</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>first-test-repo</id>
|
||||
<url>http://localhost:9428/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.my.other.repo.test</groupId>
|
||||
<artifactId>otherreleasetest</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
ff29cc2e7c14353abbfddd2356672fa3
|
||||
@@ -0,0 +1 @@
|
||||
f1e9185fe95c430181ddf79643794ea3762239c4
|
||||
@@ -0,0 +1,24 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.github.my.other.repo.test</groupId>
|
||||
<artifactId>otherreleasetest</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>second-test-repo</id>
|
||||
<url>http://localhost:9429/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.hosted.in.other.repo.test</groupId>
|
||||
<artifactId>inotherrepo</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
fb11c1bdba89ffd4a2bedc9c79fe7d66
|
||||
@@ -0,0 +1 @@
|
||||
787d45cbeba15d9e29cdd446234497df84138458
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
db083868a74964a247f8fbe409a19b63
|
||||
@@ -0,0 +1 @@
|
||||
8dea20ff7b3d0525b70f15eb9f0e2bd3056c2070
|
||||
@@ -0,0 +1,8 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.github.hosted.in.other.repo.test</groupId>
|
||||
<artifactId>inotherrepo</artifactId>
|
||||
<version>1.0</version>
|
||||
</project>
|
||||
@@ -0,0 +1 @@
|
||||
2c2065d57ce8aad45b7fa06e5faa2d8b
|
||||
@@ -0,0 +1 @@
|
||||
12d7de7581af2253d33a2b930e3715c797552700
|
||||
@@ -0,0 +1,8 @@
|
||||
import testpkg.DepClass;
|
||||
import testpkg2.DepClass2;
|
||||
|
||||
public class Test {
|
||||
|
||||
DepClass2 dc2 = DepClass.getDep2();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
diagnostics
|
||||
#select
|
||||
| DepClass |
|
||||
@@ -0,0 +1,19 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
from buildless_test_utils import *
|
||||
import subprocess
|
||||
|
||||
repo_server_process = subprocess.Popen(["python3", "-m", "http.server", "9428"], cwd = "repo")
|
||||
repo_server_process2 = subprocess.Popen(["python3", "-m", "http.server", "9429"], cwd = "repo2")
|
||||
|
||||
try:
|
||||
run_codeql_database_create([], lang="java", extra_args=["--extractor-option=buildless=true"], extra_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true"})
|
||||
finally:
|
||||
try:
|
||||
repo_server_process.kill()
|
||||
except Exception as e:
|
||||
print("Failed to kill server 1:", e, file = sys.stderr)
|
||||
repo_server_process2.kill()
|
||||
|
||||
check_buildless_fetches()
|
||||
@@ -0,0 +1,8 @@
|
||||
import java
|
||||
import semmle.code.java.Diagnostics
|
||||
|
||||
query predicate diagnostics(Diagnostic d) { any() }
|
||||
|
||||
from Class c
|
||||
where c.getName() = "DepClass"
|
||||
select c.toString()
|
||||
9
java/ql/integration-tests/all-platforms/java/buildless-gradle/.gitattributes
vendored
Normal file
9
java/ql/integration-tests/all-platforms/java/buildless-gradle/.gitattributes
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
5
java/ql/integration-tests/all-platforms/java/buildless-gradle/.gitignore
vendored
Normal file
5
java/ql/integration-tests/all-platforms/java/buildless-gradle/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This is a general purpose Gradle build.
|
||||
* To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.3/samples
|
||||
*/
|
||||
|
||||
apply plugin: 'java-library'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api 'org.apache.commons:commons-math3:3.6.1'
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"markdownMessage": "Java buildless mode used build tool Gradle to pick a JDK version and/or to recommend external dependencies.",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/using-build-tool-advice",
|
||||
"name": "Java buildless mode used build tool Gradle to pick a JDK version and/or to recommend external dependencies"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Java buildless mode used the system default JDK.",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/jdk-system-default",
|
||||
"name": "Java buildless mode used the system default JDK"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Java was extracted in buildless mode. This means that all Java source in the working directory will be scanned, with build tools such as Maven and Gradle only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/mode-active",
|
||||
"name": "Java was extracted in buildless mode"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Reading the dependency graph from Gradle build files provided 1 classpath entries",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/depgraph-provided-by-gradle",
|
||||
"name": "Java buildless mode extracted precise dependency graph information from Gradle"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# We currently have a bug where gradle tests become flaky when executed in parallel
|
||||
# - sometimes, gradle fails to connect to the gradle daemon.
|
||||
# Therefore, force this test to run sequentially.
|
||||
BIN
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
249
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradlew
vendored
Executable file
249
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradlew
vendored
Executable file
@@ -0,0 +1,249 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
92
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradlew.bat
vendored
Normal file
92
java/ql/integration-tests/all-platforms/java/buildless-gradle/gradlew.bat
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.3/userguide/building_swift_projects.html in the Gradle documentation.
|
||||
*/
|
||||
|
||||
rootProject.name = 'buildless-gradle'
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.fractestexample;
|
||||
|
||||
import org.apache.commons.math3.fraction.Fraction;
|
||||
|
||||
public class Test {
|
||||
|
||||
public Fraction test() { return Fraction.ONE; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
| src/main/java/com/fractestexample/Test.java:0:0:0:0 | Test |
|
||||
@@ -0,0 +1,8 @@
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
from buildless_test_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="java", extra_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true", "CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true"})
|
||||
|
||||
check_diagnostics()
|
||||
check_buildless_fetches()
|
||||
@@ -0,0 +1,5 @@
|
||||
import java
|
||||
|
||||
from File f
|
||||
where f.isSourceFile()
|
||||
select f
|
||||
@@ -0,0 +1,27 @@
|
||||
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/intuit/benten/benten-examples/0.1.5/benten-examples-0.1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/jakewharton/twirl/sample-runtime/1.2.0/sample-runtime-1.2.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/mattunderscore/code/generation/specky/plugin-example/0.8.0/plugin-example-0.8.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/microsoft/tang/tang-test-jarAB/0.9/tang-test-jarAB-0.9.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-example_2.11/0.1.2/rx-redis-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-json/0.5.10/minijax-example-json-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-mustache/0.5.10/minijax-example-mustache-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-petclinic/0.5.10/minijax-example-petclinic-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-security/0.5.10/minijax-example-security-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-ssl/0.5.10/minijax-example-ssl-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-todo-backend/0.5.10/minijax-example-todo-backend-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-websocket/0.5.10/minijax-example-websocket-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/scalamock/scalamock-examples_2.10/3.6.0/scalamock-examples_2.10-3.6.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/somda/sdc/glue-examples/4.0.0/glue-examples-4.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/us/fatehi/schemacrawler-examplecode/16.20.2/schemacrawler-examplecode-16.20.2.jar
|
||||
https://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar
|
||||
https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.14.0/commons-lang3-3.14.0.jar
|
||||
https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"markdownMessage": "Java buildless mode used build tool Maven to pick a JDK version and/or to recommend external dependencies.",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/using-build-tool-advice",
|
||||
"name": "Java buildless mode used build tool Maven to pick a JDK version and/or to recommend external dependencies"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Java buildless mode used the system default JDK.",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/jdk-system-default",
|
||||
"name": "Java buildless mode used the system default JDK"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Java was extracted in buildless mode. This means that all Java source in the working directory will be scanned, with build tools such as Maven and Gradle only contributing information about external dependencies.",
|
||||
"severity": "note",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/mode-active",
|
||||
"name": "Java was extracted in buildless mode"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": true,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
{
|
||||
"markdownMessage": "Reading the dependency graph from Maven build files provided 3 classpath entries",
|
||||
"severity": "unknown",
|
||||
"source": {
|
||||
"extractorName": "java",
|
||||
"id": "java/autobuilder/buildless/depgraph-provided-by-maven",
|
||||
"name": "Java buildless mode extracted precise dependency graph information from Maven"
|
||||
},
|
||||
"visibility": {
|
||||
"cliSummaryTable": true,
|
||||
"statusPage": false,
|
||||
"telemetry": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>maven-sample</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>maven-sample</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
||||
<plugins>
|
||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
</plugin>
|
||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>submod1</module>
|
||||
<module>submod2</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>submod1</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>maven-sample-submod1</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<parent>
|
||||
<artifactId>maven-sample</artifactId>
|
||||
<groupId>com.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.example;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Hello World!" );
|
||||
String expectedVersion = System.getenv("EXPECT_MAVEN");
|
||||
Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize();
|
||||
String observedVersion = mavenHome.getFileName().toString();
|
||||
if (expectedVersion != null && !expectedVersion.equals(observedVersion)) {
|
||||
System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome);
|
||||
System.exit(1);
|
||||
}
|
||||
String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX");
|
||||
String command = System.getProperty("sun.java.command");
|
||||
if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) {
|
||||
System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
version=1.0
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>A sample</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello world!</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<struts>
|
||||
This is a sample file
|
||||
</struts>
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>submod2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<name>maven-sample-submod2</name>
|
||||
<!-- FIXME change it to the project's website -->
|
||||
<url>http://www.example.com</url>
|
||||
|
||||
<parent>
|
||||
<artifactId>maven-sample</artifactId>
|
||||
<groupId>com.example</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.7</maven.compiler.source>
|
||||
<maven.compiler.target>1.7</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- depend on sibling's main and test jars -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>submod1</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>submod1</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Add a module-specific dependency -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.14.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.example;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Hello world!
|
||||
*
|
||||
*/
|
||||
public class App2
|
||||
{
|
||||
public static void main( String[] args )
|
||||
{
|
||||
System.out.println( "Hello World!" );
|
||||
String expectedVersion = System.getenv("EXPECT_MAVEN");
|
||||
Path mavenHome = Paths.get(System.getProperty("maven.home")).normalize();
|
||||
String observedVersion = mavenHome.getFileName().toString();
|
||||
if (expectedVersion != null && !expectedVersion.equals(observedVersion)) {
|
||||
System.err.println("Wrong maven version, expected '" + expectedVersion + "' but got '" + observedVersion + "'" + mavenHome);
|
||||
System.exit(1);
|
||||
}
|
||||
String commandMatcher = System.getenv("EXPECT_COMMAND_REGEX");
|
||||
String command = System.getProperty("sun.java.command");
|
||||
if (commandMatcher != null && !Pattern.matches(commandMatcher, command)) {
|
||||
System.err.println("Wrong command line, '" + command + "' does not match '" + commandMatcher + "'");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
version=1.0
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>A sample</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello world!</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<struts>
|
||||
This is a sample file
|
||||
</struts>
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class AppTest2
|
||||
{
|
||||
/**
|
||||
* Rigorous Test :-)
|
||||
*/
|
||||
@Test
|
||||
public void shouldAnswerWithTrue()
|
||||
{
|
||||
assertTrue( true );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#select
|
||||
| submod1/src/main/java/com/example/App.java:0:0:0:0 | App |
|
||||
| submod1/src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
|
||||
| submod2/src/main/java/com/example/App2.java:0:0:0:0 | App2 |
|
||||
| submod2/src/test/java/com/example/AppTest2.java:0:0:0:0 | AppTest2 |
|
||||
xmlFiles
|
||||
| pom.xml:0:0:0:0 | pom.xml |
|
||||
| submod1/pom.xml:0:0:0:0 | submod1/pom.xml |
|
||||
| submod1/src/main/resources/page.xml:0:0:0:0 | submod1/src/main/resources/page.xml |
|
||||
| submod1/src/main/resources/struts.xml:0:0:0:0 | submod1/src/main/resources/struts.xml |
|
||||
| submod2/pom.xml:0:0:0:0 | submod2/pom.xml |
|
||||
| submod2/src/main/resources/page.xml:0:0:0:0 | submod2/src/main/resources/page.xml |
|
||||
| submod2/src/main/resources/struts.xml:0:0:0:0 | submod2/src/main/resources/struts.xml |
|
||||
propertiesFiles
|
||||
| submod1/src/main/resources/my-app.properties:0:0:0:0 | submod1/src/main/resources/my-app.properties |
|
||||
| submod2/src/main/resources/my-app.properties:0:0:0:0 | submod2/src/main/resources/my-app.properties |
|
||||
| test-db/log/ext/javac.properties:0:0:0:0 | test-db/log/ext/javac.properties |
|
||||
@@ -0,0 +1,8 @@
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
from buildless_test_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="java", extra_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true", "CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true"})
|
||||
|
||||
check_diagnostics()
|
||||
check_buildless_fetches()
|
||||
@@ -0,0 +1,9 @@
|
||||
import java
|
||||
|
||||
from File f
|
||||
where f.isSourceFile()
|
||||
select f
|
||||
|
||||
query predicate xmlFiles(XmlFile x) { any() }
|
||||
|
||||
query predicate propertiesFiles(File f) { f.getExtension() = "properties" }
|
||||
@@ -0,0 +1,26 @@
|
||||
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/intuit/benten/benten-examples/0.1.5/benten-examples-0.1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/jakewharton/twirl/sample-runtime/1.2.0/sample-runtime-1.2.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/mattunderscore/code/generation/specky/plugin-example/0.8.0/plugin-example-0.8.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/microsoft/tang/tang-test-jarAB/0.9/tang-test-jarAB-0.9.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-example_2.11/0.1.2/rx-redis-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-json/0.5.10/minijax-example-json-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-mustache/0.5.10/minijax-example-mustache-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-petclinic/0.5.10/minijax-example-petclinic-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-security/0.5.10/minijax-example-security-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-ssl/0.5.10/minijax-example-ssl-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-todo-backend/0.5.10/minijax-example-todo-backend-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-websocket/0.5.10/minijax-example-websocket-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/scalamock/scalamock-examples_2.10/3.6.0/scalamock-examples_2.10-3.6.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/somda/sdc/glue-examples/4.0.0/glue-examples-4.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/us/fatehi/schemacrawler-examplecode/16.20.2/schemacrawler-examplecode-16.20.2.jar
|
||||
https://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar
|
||||
https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
|
||||
@@ -0,0 +1,26 @@
|
||||
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
|
||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/intuit/benten/benten-examples/0.1.5/benten-examples-0.1.5.jar
|
||||
https://repo.maven.apache.org/maven2/com/jakewharton/twirl/sample-runtime/1.2.0/sample-runtime-1.2.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/mattunderscore/code/generation/specky/plugin-example/0.8.0/plugin-example-0.8.0.jar
|
||||
https://repo.maven.apache.org/maven2/com/microsoft/tang/tang-test-jarAB/0.9/tang-test-jarAB-0.9.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-example_2.11/0.1.2/rx-redis-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
|
||||
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-json/0.5.10/minijax-example-json-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-mustache/0.5.10/minijax-example-mustache-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-petclinic/0.5.10/minijax-example-petclinic-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-security/0.5.10/minijax-example-security-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-ssl/0.5.10/minijax-example-ssl-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-todo-backend/0.5.10/minijax-example-todo-backend-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-websocket/0.5.10/minijax-example-websocket-0.5.10.jar
|
||||
https://repo.maven.apache.org/maven2/org/scalamock/scalamock-examples_2.10/3.6.0/scalamock-examples_2.10-3.6.0.jar
|
||||
https://repo.maven.apache.org/maven2/org/somda/sdc/glue-examples/4.0.0/glue-examples-4.0.0.jar
|
||||
https://repo.maven.apache.org/maven2/us/fatehi/schemacrawler-examplecode/16.20.2/schemacrawler-examplecode-16.20.2.jar
|
||||
https://repo1.maven.org/maven2/junit/junit/4.11/junit-4.11.jar
|
||||
https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
|
||||
@@ -0,0 +1,10 @@
|
||||
#select
|
||||
| src/main/java/com/example/App.java:0:0:0:0 | App |
|
||||
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
|
||||
xmlFiles
|
||||
| pom.xml:0:0:0:0 | pom.xml |
|
||||
| src/main/resources/page.xml:0:0:0:0 | src/main/resources/page.xml |
|
||||
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
|
||||
propertiesFiles
|
||||
| src/main/resources/my-app.properties:0:0:0:0 | src/main/resources/my-app.properties |
|
||||
| test-db/log/ext/javac.properties:0:0:0:0 | test-db/log/ext/javac.properties |
|
||||
@@ -1,8 +1,10 @@
|
||||
#select
|
||||
| src/main/java/com/example/App.java:0:0:0:0 | App |
|
||||
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
|
||||
xmlFiles
|
||||
| pom.xml:0:0:0:0 | pom.xml |
|
||||
| src/main/resources/page.xml:0:0:0:0 | src/main/resources/page.xml |
|
||||
| src/main/resources/struts.xml:0:0:0:0 | src/main/resources/struts.xml |
|
||||
propertiesFiles
|
||||
#select
|
||||
| src/main/java/com/example/App.java:0:0:0:0 | App |
|
||||
| src/test/java/com/example/AppTest.java:0:0:0:0 | AppTest |
|
||||
| src/main/resources/my-app.properties:0:0:0:0 | src/main/resources/my-app.properties |
|
||||
| test-db/log/ext/javac.properties:0:0:0:0 | test-db/log/ext/javac.properties |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import sys
|
||||
|
||||
from create_database_utils import *
|
||||
from diagnostics_test_utils import *
|
||||
from buildless_test_utils import *
|
||||
|
||||
run_codeql_database_create([], lang="java", extra_env={"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true", "CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true"})
|
||||
|
||||
check_diagnostics()
|
||||
check_buildless_fetches()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user