+
+Extracting Compressed files with any compression algorithm like gzip can cause denial of service attacks.
+Attackers can compress a huge file consisting of repeated similiar bytes into a small compressed file.
+
+
+
+When you want to decompress a user-provided compressed file you must be careful about the decompression ratio or read these files within a loop byte by byte to be able to manage the decompressed size in each cycle of the loop.
+
+
+
+
+
+Reading an uncompressed Gzip file within a loop and check for a threshold size in each cycle.
+
+
+
+
+The following example is unsafe, as we do not check the uncompressed size.
+
+
+
+
+
+
+
+
+Zlib documentation
+
+
+
+An explanation of the attack
+
+
+
+
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql b/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql
new file mode 100644
index 000000000000..bfa11e65b067
--- /dev/null
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-409/DecompressionBombs.ql
@@ -0,0 +1,40 @@
+/**
+ * @name User-controlled file decompression
+ * @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous
+ * @kind path-problem
+ * @problem.severity error
+ * @precision low
+ * @id cpp/data-decompression-bomb
+ * @tags security
+ * experimental
+ * external/cwe/cwe-409
+ */
+
+import cpp
+import semmle.code.cpp.security.FlowSources
+import DecompressionBomb
+
+predicate isSink(FunctionCall fc, DataFlow::Node sink) {
+ exists(DecompressionFunction f | fc.getTarget() = f |
+ fc.getArgument(f.getArchiveParameterIndex()) = [sink.asExpr(), sink.asIndirectExpr()]
+ )
+}
+
+module DecompressionTaintConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
+
+ predicate isSink(DataFlow::Node sink) { isSink(_, sink) }
+
+ predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ any(DecompressionFlowStep s).isAdditionalFlowStep(node1, node2)
+ }
+}
+
+module DecompressionTaint = TaintTracking::Global