Skip to content

Commit 56bc32f

Browse files
committed
add libarchive
1 parent d4d505d commit 56bc32f

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* @name User-controlled file decompression
3+
* @description User-controlled data that flows into decompression library APIs without checking the compression rate is dangerous
4+
* @kind path-problem
5+
* @problem.severity error
6+
* @security-severity 7.8
7+
* @precision high
8+
* @id cpp/user-controlled-file-decompression-libarchive
9+
* @tags security
10+
* experimental
11+
* external/cwe/cwe-409
12+
*/
13+
14+
import cpp
15+
import semmle.code.cpp.ir.dataflow.TaintTracking
16+
import semmle.code.cpp.security.FlowSources
17+
18+
/**
19+
* The `archive_read_new` function as a Flow source
20+
* create a `archive` instance
21+
*/
22+
private class Archive_read_new extends Function {
23+
Archive_read_new() { this.hasGlobalName("archive_read_new") }
24+
}
25+
26+
/**
27+
* The `archive_read_data*` functions are used in Flow Sink
28+
* [Examples](https://github.com/libarchive/libarchive/wiki/Examples)
29+
*/
30+
private class Archive_read_data_block extends Function {
31+
Archive_read_data_block() {
32+
this.hasGlobalName(["archive_read_data_block", "archive_read_data", "archive_read_data_into_fd"])
33+
}
34+
}
35+
36+
module LibArchiveTaintConfig implements DataFlow::StateConfigSig {
37+
class FlowState = DataFlow::FlowState;
38+
39+
predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
40+
exists(FunctionCall fc | fc.getTarget() instanceof Archive_read_new |
41+
fc.getArgument(0) = source.asExpr() and
42+
state = "unzFile"
43+
)
44+
}
45+
46+
predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
47+
exists(FunctionCall fc | fc.getTarget() instanceof Archive_read_data_block |
48+
fc.getArgument(1) = sink.asExpr() and
49+
state = "unzFile"
50+
)
51+
}
52+
53+
predicate isAdditionalFlowStep(
54+
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
55+
DataFlow::FlowState state2
56+
) {
57+
exists(FunctionCall fc | fc.getTarget() instanceof Archive_read_data_block |
58+
node1.asExpr() = fc.getArgument(0) and
59+
node2.asExpr() = fc.getArgument(1) and
60+
state1 = "" and
61+
state2 = "mz_zip_reader"
62+
)
63+
}
64+
65+
predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() }
66+
}
67+
68+
module LibArchiveTaint = TaintTracking::GlobalWithState<LibArchiveTaintConfig>;
69+
70+
import LibArchiveTaint::PathGraph
71+
72+
from LibArchiveTaint::PathNode source, LibArchiveTaint::PathNode sink
73+
where LibArchiveTaint::flowPath(source, sink)
74+
select sink.getNode(), source, sink, "This Decompressiondepends on a $@.", source.getNode(),
75+
"potentially untrusted source"

0 commit comments

Comments
 (0)