@@ -5,8 +5,9 @@ module DecompressionBombs {
5
5
FlowState ( ) {
6
6
this =
7
7
[
8
- "ZstdNewReader" , "XzNewReader" , "GzipNewReader" , "S2NewReader" , "SnappyNewReader" ,
9
- "ZlibNewReader" , "FlateNewReader" , "Bzip2NewReader" , "ZipOpenReader" , "ZipKlauspost" , ""
8
+ "ZstdNewReader" , "XzNewReader" , "GzipNewReader" , "PgzipNewReader" , "S2NewReader" ,
9
+ "SnappyNewReader" , "ZlibNewReader" , "FlateNewReader" , "Bzip2NewReader" , "ZipOpenReader" ,
10
+ "ZipKlauspost" , ""
10
11
]
11
12
}
12
13
}
@@ -252,11 +253,12 @@ module DecompressionBombs {
252
253
/**
253
254
* Provides decompression bomb sinks and additional flow steps for `github.com/klauspost/compress/gzip` package
254
255
*/
255
- module KlauspostGzip {
256
+ module KlauspostGzipAndPgzip {
256
257
class TheSink extends Sink {
257
258
TheSink ( ) {
258
259
exists ( Method f |
259
- f .hasQualifiedName ( "github.com/klauspost/compress/gzip" , "Reader" , "Read" )
260
+ f .hasQualifiedName ( [ "github.com/klauspost/compress/gzip" , "github.com/klauspost/pgzip" ] ,
261
+ "Reader" , "Read" )
260
262
|
261
263
this = f .getACall ( ) .getReceiver ( )
262
264
)
@@ -277,10 +279,15 @@ module DecompressionBombs {
277
279
DataFlow:: Node fromNode , FlowState fromState , DataFlow:: Node toNode , FlowState toState
278
280
) {
279
281
exists ( Function f , DataFlow:: CallNode call |
280
- f .hasQualifiedName ( [ "github.com/klauspost/compress/gzip" , "github.com/klauspost/pgzip" ] ,
281
- "NewReader" ) and
282
- call = f .getACall ( )
283
- |
282
+ f .hasQualifiedName ( "github.com/klauspost/pgzip" , "NewReader" ) and
283
+ call = f .getACall ( ) and
284
+ fromNode = call .getArgument ( 0 ) and
285
+ toNode = call .getResult ( 0 ) and
286
+ fromState = "" and
287
+ toState = "PgzipNewReader"
288
+ or
289
+ f .hasQualifiedName ( "github.com/klauspost/compress/gzip" , "NewReader" ) and
290
+ call = f .getACall ( ) and
284
291
fromNode = call .getArgument ( 0 ) and
285
292
toNode = call .getResult ( 0 ) and
286
293
fromState = "" and
@@ -651,7 +658,15 @@ module DecompressionBombs {
651
658
module GeneralReadIoSink {
652
659
class TheSink extends Sink {
653
660
TheSink ( ) {
654
- exists ( Function f | f .hasQualifiedName ( "io" , [ "Copy" , "CopyBuffer" , "CopyN" ] ) |
661
+ exists ( Function f , DataFlow:: CallNode cn |
662
+ f .hasQualifiedName ( "io" , "CopyN" ) and cn = f .getACall ( )
663
+ |
664
+ this = cn .getArgument ( 1 ) and
665
+ // and the return value doesn't flow into a comparison (<, >, <=, >=).
666
+ not localStep * ( cn .getResult ( 0 ) , any ( DataFlow:: RelationalComparisonNode rcn ) .getAnOperand ( ) )
667
+ )
668
+ or
669
+ exists ( Function f | f .hasQualifiedName ( "io" , [ "Copy" , "CopyBuffer" ] ) |
655
670
this = f .getACall ( ) .getArgument ( 1 )
656
671
)
657
672
or
@@ -677,5 +692,29 @@ module DecompressionBombs {
677
692
)
678
693
}
679
694
}
695
+
696
+ /**
697
+ * Holds if the value of `pred` can flow into `succ` in one step through an
698
+ * arithmetic operation (other than remainder).
699
+ *
700
+ * Note: this predicate is copied from AllocationSizeOverflow. When this query
701
+ * is promoted it should be put in a shared location.
702
+ */
703
+ predicate additionalStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
704
+ succ .asExpr ( ) .( ArithmeticExpr ) .getAnOperand ( ) = pred .asExpr ( ) and
705
+ not succ .asExpr ( ) instanceof RemExpr
706
+ }
707
+
708
+ /**
709
+ * Holds if the value of `pred` can flow into `succ` in one step, either by a standard taint step
710
+ * or by an additional step.
711
+ *
712
+ * Note: this predicate is copied from AllocationSizeOverflow. When this query
713
+ * is promoted it should be put in a shared location.
714
+ */
715
+ predicate localStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
716
+ TaintTracking:: localTaintStep ( pred , succ ) or
717
+ additionalStep ( pred , succ )
718
+ }
680
719
}
681
720
}
0 commit comments