+
+
+
+The Thread.sleep method is used to pause the execution of current thread for
+specified time. When the sleep time is user-controlled, especially in the web application context,
+it can be abused to cause all of a server's threads to sleep, leading to denial of service.
+
+
+
+To guard against this attack, consider specifying an upper range of allowed sleep time or adopting
+the producer/consumer design pattern with Object.wait method to avoid performance
+problems or even resource exhaustion. For more information, refer to the concurrency tutorial of Oracle
+listed below or java/ql/src/Likely Bugs/Concurrency queries of CodeQL.
+
+
+
+The following example shows a bad situation and a good situation respectively. In the bad situation,
+a thread sleep time comes directly from user input. In the good situation, an upper
+range check on the maximum sleep time allowed is enforced.
+
+
+
+
+
+Snyk:
+Denial of Service (DoS)
+in com.googlecode.gwtupload:gwtupload.
+
+
+gwtupload:
+[Fix DOS issue] Updating the
+AbstractUploadListener.java file.
+
+
+The blog of a gypsy engineer:
+
+CVE-2019-17555: DoS via Retry-After header in Apache Olingo.
+
+
+Oracle:
+The Java Concurrency Tutorials
+
+
+
diff --git a/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql
index 3c3c58da449..f66235994b0 100644
--- a/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql
+++ b/java/ql/src/experimental/Security/CWE/CWE-400/LocalThreadResourceAbuse.ql
@@ -3,7 +3,7 @@
* @description Using user input directly to control a thread's sleep time could lead to
* performance problems or even resource exhaustion.
* @kind path-problem
- * @id java/thread-resource-abuse
+ * @id java/local-thread-resource-abuse
* @problem.severity recommendation
* @tags security
* external/cwe/cwe-400
diff --git a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql b/java/ql/src/utils/model-generator/CaptureNeutralModels.ql
similarity index 60%
rename from java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql
rename to java/ql/src/utils/model-generator/CaptureNeutralModels.ql
index a6f6e5f26e5..96744de89b6 100644
--- a/java/ql/src/utils/model-generator/CaptureNegativeSummaryModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureNeutralModels.ql
@@ -1,8 +1,8 @@
/**
- * @name Capture negative summary models.
- * @description Finds negative summary models to be used by other queries.
+ * @name Capture neutral models.
+ * @description Finds neutral models to be used by other queries.
* @kind diagnostic
- * @id java/utils/model-generator/negative-summary-models
+ * @id java/utils/model-generator/neutral-models
* @tags model-generator
*/
diff --git a/java/ql/src/utils/model-generator/RegenerateModels.py b/java/ql/src/utils/model-generator/RegenerateModels.py
index f89873339f5..6bea57793a0 100755
--- a/java/ql/src/utils/model-generator/RegenerateModels.py
+++ b/java/ql/src/utils/model-generator/RegenerateModels.py
@@ -2,7 +2,6 @@
# Tool to regenerate existing framework CSV models.
-from pathlib import Path
import json
import os
import shutil
@@ -37,7 +36,7 @@ def regenerateModel(lgtmSlug, extractedDb):
modelFile = lgtmSlugToModelFile[lgtmSlug]
codeQlRoot = findGitRoot()
subprocess.check_call([codeQlRoot + "/java/ql/src/utils/model-generator/GenerateFlowModel.py",
- "--with-summaries", "--with-sinks", "--with-negative-summaries",
+ "--with-summaries", "--with-sinks", "--with-neutrals",
extractedDb, modelFile])
print("Regenerated " + modelFile)
shutil.rmtree(tmpDir)
diff --git a/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql b/java/ql/src/utils/modelconverter/ExtractNeutrals.ql
similarity index 50%
rename from java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql
rename to java/ql/src/utils/modelconverter/ExtractNeutrals.ql
index e762b3ee6e5..ad7cef84f04 100644
--- a/java/ql/src/utils/modelconverter/ExtractNegativeSummaries.ql
+++ b/java/ql/src/utils/modelconverter/ExtractNeutrals.ql
@@ -1,7 +1,7 @@
/**
- * @name Extract MaD negative summary model rows.
- * @description This extracts the Models as data negative summary model rows.
- * @id java/utils/modelconverter/generate-data-extensions-negative-summary
+ * @name Extract MaD neutral model rows.
+ * @description This extracts the Models as data neutral model rows.
+ * @id java/utils/modelconverter/generate-data-extensions-neutral
*/
import java
@@ -9,6 +9,6 @@ import semmle.code.java.dataflow.ExternalFlow
from string package, string type, string name, string signature, string provenance
where
- negativeSummaryModel(package, type, name, signature, provenance) and
+ neutralModel(package, type, name, signature, provenance) and
provenance != "generated"
select package, type, name, signature, provenance order by package, type, name, signature
diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
index f40b028ba6d..893c62191b3 100644
--- a/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
+++ b/java/ql/src/utils/modelgenerator/internal/CaptureModels.qll
@@ -58,9 +58,7 @@ private string asSummaryModel(TargetApiSpecific api, string input, string output
+ "generated"
}
-string asNegativeSummaryModel(TargetApiSpecific api) {
- result = asPartialNegativeModel(api) + "generated"
-}
+string asNeutralModel(TargetApiSpecific api) { result = asPartialNeutralModel(api) + "generated" }
/**
* Gets the value summary model for `api` with `input` and `output`.
diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll
index 6e9fe7c29b2..af46170f5a3 100644
--- a/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll
+++ b/java/ql/src/utils/modelgenerator/internal/CaptureModelsSpecific.qll
@@ -131,9 +131,9 @@ string asPartialModel(TargetApiSpecific api) {
}
/**
- * Computes the first 4 columns for negative CSV rows.
+ * Computes the first 4 columns for neutral CSV rows.
*/
-string asPartialNegativeModel(TargetApiSpecific api) {
+string asPartialNeutralModel(TargetApiSpecific api) {
exists(string type, string name, string parameters |
partialModel(api, type, name, parameters) and
result =
diff --git a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll
index 4b5293e63cd..04e87d9a385 100644
--- a/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll
+++ b/java/ql/src/utils/modelgenerator/internal/CaptureSummaryFlow.qll
@@ -77,10 +77,10 @@ string captureFlow(DataFlowTargetApi api) {
}
/**
- * Gets the negative summary for `api`, if any.
- * A negative summary is generated, if there does not exist any positive flow.
+ * Gets the neutral summary for `api`, if any.
+ * A neutral model is generated, if there does not exist any summary model.
*/
string captureNoFlow(DataFlowTargetApi api) {
not exists(captureFlow(api)) and
- result = asNegativeSummaryModel(api)
+ result = asNeutralModel(api)
}
diff --git a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected
index 1aedc93eb9a..dd3f886ccb1 100644
--- a/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected
+++ b/java/ql/test/experimental/query-tests/security/CWE-089/src/main/MyBatisAnnotationSqlInjection.expected
@@ -1,30 +1,45 @@
edges
| MybatisSqlInjection.java:62:19:62:43 | name : String | MybatisSqlInjection.java:63:35:63:38 | name : String |
| MybatisSqlInjection.java:63:35:63:38 | name : String | MybatisSqlInjectionService.java:48:19:48:29 | name : String |
-| MybatisSqlInjection.java:94:20:94:44 | name : String | MybatisSqlInjection.java:95:36:95:39 | name : String |
-| MybatisSqlInjection.java:95:36:95:39 | name : String | MybatisSqlInjectionService.java:76:20:76:30 | name : String |
-| MybatisSqlInjection.java:99:20:99:43 | age : String | MybatisSqlInjection.java:100:36:100:38 | age : String |
-| MybatisSqlInjection.java:100:36:100:38 | age : String | MybatisSqlInjectionService.java:80:20:80:29 | age : String |
+| MybatisSqlInjection.java:67:46:67:70 | name : String | MybatisSqlInjection.java:68:40:68:43 | name : String |
+| MybatisSqlInjection.java:68:40:68:43 | name : String | MybatisSqlInjectionService.java:54:32:54:42 | name : String |
+| MybatisSqlInjection.java:99:20:99:44 | name : String | MybatisSqlInjection.java:100:36:100:39 | name : String |
+| MybatisSqlInjection.java:100:36:100:39 | name : String | MybatisSqlInjectionService.java:80:20:80:30 | name : String |
+| MybatisSqlInjection.java:104:20:104:43 | age : String | MybatisSqlInjection.java:105:36:105:38 | age : String |
+| MybatisSqlInjection.java:105:36:105:38 | age : String | MybatisSqlInjectionService.java:84:20:84:29 | age : String |
+| MybatisSqlInjection.java:109:46:109:70 | name : String | MybatisSqlInjection.java:110:40:110:43 | name : String |
+| MybatisSqlInjection.java:110:40:110:43 | name : String | MybatisSqlInjectionService.java:88:32:88:42 | name : String |
| MybatisSqlInjectionService.java:48:19:48:29 | name : String | MybatisSqlInjectionService.java:50:23:50:26 | name : String |
| MybatisSqlInjectionService.java:50:3:50:9 | hashMap [post update] [