@@ -6,12 +6,6 @@ private import codeql.ruby.DataFlow
66private import codeql.ruby.dataflow.FlowSummary
77private import codeql.ruby.dataflow.internal.DataFlowDispatch
88
9- // TODO: the way we interpret `preservesValue` in this module may not be
10- // correct: we assume that if the input string appears intact in the output,
11- // then value is preserves. This means that we consider appending or prepending
12- // characters to the string to be value-preserving.
13- // We may want to be stricter here, and define value-preserving as when the
14- // output string exactly matches the input string.
159/**
1610 * Provides flow summaries for the `String` class.
1711 *
@@ -79,7 +73,7 @@ module String {
7973 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
8074 input = [ "Receiver" , "Argument[0]" , "ArrayElement of Argument[0]" ] and
8175 output = "ReturnValue" and
82- preservesValue = true
76+ preservesValue = false
8377 }
8478 }
8579
@@ -110,7 +104,7 @@ module String {
110104 override MethodCall getACall ( ) { result = mc }
111105
112106 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
113- valueIdentityFlow ( input , output , preservesValue )
107+ taintIdentityFlow ( input , output , preservesValue )
114108 }
115109 }
116110
@@ -138,13 +132,10 @@ module String {
138132 CenterSummary ( ) { this = [ "center" , "ljust" , "rjust" ] }
139133
140134 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
141- (
142- input = "Receiver" and
143- output = "ReturnValue"
144- or
145- input = "Argument[1]" and
146- output = "ReturnValue"
147- ) and
135+ taintIdentityFlow ( input , output , preservesValue )
136+ or
137+ input = "Argument[1]" and
138+ output = "ReturnValue" and
148139 preservesValue = false
149140 }
150141 }
@@ -160,13 +151,12 @@ module String {
160151 override MethodCall getACall ( ) { result = mc }
161152
162153 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
154+ taintIdentityFlow ( input , output , preservesValue )
155+ or
156+ this = [ "chomp!" , "chop!" ] and
163157 input = "Receiver" and
164158 preservesValue = false and
165- (
166- output = "ReturnValue"
167- or
168- this = [ "chomp!" , "chop!" ] and output = "Receiver"
169- )
159+ output = "Receiver"
170160 }
171161 }
172162
@@ -185,7 +175,7 @@ module String {
185175 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
186176 input = [ "Receiver" , "Argument[_]" ] and
187177 output = [ "ReturnValue" , "Receiver" ] and
188- preservesValue = true
178+ preservesValue = false
189179 }
190180 }
191181
@@ -279,9 +269,7 @@ module String {
279269 ForceEncodingSummary ( ) { this = "force_encoding" }
280270
281271 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
282- input = "Receiver" and
283- output = "ReturnValue" and
284- preservesValue = false
272+ taintIdentityFlow ( input , output , preservesValue )
285273 }
286274 }
287275
@@ -309,13 +297,9 @@ module String {
309297 // receiver -> return value
310298 // replacement -> return value
311299 // block return -> return value
312- (
313- input = [ "Receiver" , "Argument[1]" ] and
314- preservesValue = false
315- or
316- input = "ReturnValue of BlockArgument" and preservesValue = true
317- ) and
318- output = "ReturnValue"
300+ preservesValue = false and
301+ output = "ReturnValue" and
302+ input = [ "Receiver" , "Argument[1]" , "ReturnValue of BlockArgument" ]
319303 }
320304 }
321305
@@ -330,12 +314,9 @@ module String {
330314 }
331315
332316 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
333- (
334- input = "Receiver" and preservesValue = false
335- or
336- input = "Argument[1]" and preservesValue = true
337- ) and
338- output = "ReturnValue"
317+ taintIdentityFlow ( input , output , preservesValue )
318+ or
319+ input = "Argument[1]" and output = "ReturnValue" and preservesValue = false
339320 }
340321 }
341322
@@ -357,7 +338,7 @@ module String {
357338 StripSummary ( ) { this = [ "strip" , "lstrip" , "rstrip" ] + [ "" , "!" ] }
358339
359340 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
360- valueIdentityFlow ( input , output , preservesValue )
341+ taintIdentityFlow ( input , output , preservesValue )
361342 }
362343 }
363344
@@ -427,14 +408,14 @@ module String {
427408
428409 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
429410 input = "Receiver" and
430- (
431- // Parameter[_] doesn't seem to work
432- output = "Parameter[" + [ 0 .. 10 ] + "] of BlockArgument" and preservesValue = false
433- or
434- // scan(pattern) -> array
435- output = "ReturnValue" and
436- preservesValue = true
437- )
411+ preservesValue = false and
412+ output =
413+ [
414+ // scan(pattern) -> array
415+ "ReturnValue" ,
416+ // Parameter[_] doesn't seem to work
417+ "Parameter[" + [ 0 .. 10 ] + "] of BlockArgument"
418+ ]
438419 }
439420 }
440421
@@ -443,14 +424,14 @@ module String {
443424
444425 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
445426 input = "Receiver" and
446- (
447- // scan(pattern) {|match, ...| block } -> str
448- output = "ArrayElement[?] of ReturnValue" and
449- preservesValue = false
450- or
451- // Parameter[_] doesn't seem to work
452- output = "Parameter[" + [ 0 .. 10 ] + "] of BlockArgument" and preservesValue = false
453- )
427+ preservesValue = false and
428+ output =
429+ [
430+ // scan(pattern) {|match, ...| block } -> str
431+ "ArrayElement[?] of ReturnValue" ,
432+ // Parameter[_] doesn't seem to work
433+ "Parameter[" + [ 0 .. 10 ] + "] of BlockArgument"
434+ ]
454435 }
455436 }
456437
@@ -470,35 +451,48 @@ module String {
470451 ScrubBlockSummary ( ) { this = "scrub_block" and exists ( mc .getBlock ( ) ) }
471452
472453 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
473- input = "Receiver" and
474- output = "Parameter[0] of BlockArgument" and
475- preservesValue = true
476- or
477- input = "Argument[0]" and output = "ReturnValue" and preservesValue = true
478- or
479- input = "ReturnValue of BlockArgument" and
480- output = "ReturnValue" and
481- preservesValue = true
482- or
483454 taintIdentityFlow ( input , output , preservesValue )
455+ or
456+ preservesValue = false and
457+ (
458+ input = "Receiver" and
459+ output = "Parameter[0] of BlockArgument"
460+ or
461+ input = "Argument[0]" and output = "ReturnValue"
462+ or
463+ input = "ReturnValue of BlockArgument" and
464+ output = "ReturnValue"
465+ )
484466 }
485467 }
486468
487469 private class ScrubNoBlockSummary extends ScrubSummary {
488470 ScrubNoBlockSummary ( ) { this = "scrub_no_block" and not exists ( mc .getBlock ( ) ) }
489471
490472 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
491- input = "Receiver" and
492- output = "Parameter[0] of BlockArgument" and
493- preservesValue = true
494- or
495- input = "Argument[0]" and output = "ReturnValue" and preservesValue = true
473+ taintIdentityFlow ( input , output , preservesValue )
496474 or
475+ preservesValue = false and
476+ (
477+ input = "Receiver" and
478+ output = "Parameter[0] of BlockArgument"
479+ or
480+ input = "Argument[0]" and output = "ReturnValue"
481+ )
482+ }
483+ }
484+
485+ /**
486+ * A flow summary for `String#shellescape`.
487+ */
488+ private class ShellescapeSummary extends SimpleSummarizedCallable {
489+ ShellescapeSummary ( ) { this = "shellescape" }
490+
491+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
497492 taintIdentityFlow ( input , output , preservesValue )
498493 }
499494 }
500495
501- // TODO: what do we do about `String#shellescape`?
502496 /**
503497 * A flow summary for `String#shellsplit`.
504498 */
@@ -552,7 +546,9 @@ module String {
552546 TrSummary ( ) { this = [ "tr" , "tr_s" ] + [ "" , "!" ] }
553547
554548 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
555- input = [ "Receiver" , "Argument[1]" ] and output = "ReturnValue" and preservesValue = false
549+ taintIdentityFlow ( input , output , preservesValue )
550+ or
551+ input = "Argument[1]" and output = "ReturnValue" and preservesValue = false
556552 }
557553 }
558554
@@ -604,7 +600,7 @@ module String {
604600 }
605601
606602 override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
607- input = [ "Receiver" ] and
603+ input = "Receiver" and
608604 output = "Parameter[0] of BlockArgument" and
609605 preservesValue = true
610606 or
0 commit comments