33 */
44
55import go
6+ private import semmle.go.dataflow.FlowSummary
7+ private import semmle.go.dataflow.internal.DataFlowPrivate
68
79/** Provides models of commonly used functions in the `net/http` package. */
810module NetHttp {
@@ -120,6 +122,18 @@ module NetHttp {
120122 }
121123 }
122124
125+ private DataFlow:: Node getSummaryInputOrOutputNode (
126+ DataFlow:: CallNode call , SummaryComponentStack stack
127+ ) {
128+ exists ( int n |
129+ stack = SummaryComponentStack:: argument ( n ) and
130+ result = call .getArgument ( n )
131+ )
132+ or
133+ stack = SummaryComponentStack:: argument ( - 1 ) and
134+ result = call .getReceiver ( )
135+ }
136+
123137 private class ResponseBody extends Http:: ResponseBody:: Range , DataFlow:: ArgumentNode {
124138 DataFlow:: Node responseWriter ;
125139
@@ -131,13 +145,30 @@ module NetHttp {
131145 responseWriter = call .( DataFlow:: MethodCallNode ) .getReceiver ( )
132146 )
133147 or
134- // FIXME
135148 exists ( TaintTracking:: FunctionModel model |
136149 // A modeled function conveying taint from some input to the response writer,
137150 // e.g. `io.Copy(responseWriter, someTaintedReader)`
138151 model .taintStep ( this , responseWriter ) and
139152 responseWriter .getType ( ) .implements ( "net/http" , "ResponseWriter" )
140153 )
154+ or
155+ exists (
156+ SummarizedCallable callable , DataFlow:: CallNode call , SummaryComponentStack input ,
157+ SummaryComponentStack output
158+ |
159+ callable = call .getACalleeIncludingExternals ( ) and callable .propagatesFlow ( input , output , _)
160+ |
161+ // A modeled function conveying taint from some input to the response writer,
162+ // e.g. `io.Copy(responseWriter, someTaintedReader)`
163+ // NB. SummarizedCallables do not implement a direct call-site-crossing flow step; instead
164+ // they are implemented by a function body with internal dataflow nodes, so we mimic the
165+ // one-step style for the particular case of taint propagation direct from an argument or receiver
166+ // to another argument, receiver or return value without an
167+ this = getSummaryInputOrOutputNode ( call , input ) and
168+ responseWriter .( DataFlow:: PostUpdateNode ) .getPreUpdateNode ( ) =
169+ getSummaryInputOrOutputNode ( call , output ) and
170+ responseWriter .getType ( ) .implements ( "net/http" , "ResponseWriter" )
171+ )
141172 }
142173
143174 override Http:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = responseWriter }
0 commit comments