@@ -8,8 +8,6 @@ import go
88 * Provides classes for working with concepts from the [`clevergo.tech/clevergo@v0.5.2`](https://pkg.go.dev/clevergo.tech/clevergo@v0.5.2) package.
99 */
1010private module CleverGo {
11- /** Gets the package path. */
12- bindingset [ result ]
1311 string packagePath ( ) {
1412 result = package ( [ "clevergo.tech/clevergo" , "github.com/clevergo/clevergo" ] , "" )
1513 }
@@ -213,112 +211,14 @@ private module CleverGo {
213211 override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
214212 }
215213
216- /**
217- * Models HTTP ResponseBody where the content-type can be dynamically set by the caller.
218- */
219- private class HttpResponseBodyDynamicContentType extends HTTP:: ResponseBody:: Range {
220- DataFlow:: Node contentTypeNode ;
221- DataFlow:: Node receiverNode ;
222-
223- HttpResponseBodyDynamicContentType ( ) {
224- exists ( string package , string receiverName |
225- setsBodyAndDynamicContentType ( package , receiverName , this , contentTypeNode , receiverNode )
226- )
227- }
228-
229- override DataFlow:: Node getAContentTypeNode ( ) { result = contentTypeNode }
230-
231- override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
232- }
233-
234- /**
235- * Models HTTP ResponseBody where the content-type is set by another call.
236- */
237- private class HttpResponseBodyNoContentType extends HTTP:: ResponseBody:: Range {
238- private DataFlow:: Node receiverNode ;
239-
240- HttpResponseBodyNoContentType ( ) {
241- exists ( string package , string receiverName |
242- setsBody ( package , receiverName , receiverNode , this )
243- )
244- }
245-
246- override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
247- }
248-
249- /**
250- * Models an HTTP static content-type setter for package: clevergo.tech/clevergo@v0.5.2
251- */
252- private class StaticContentTypeSetter extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
253- DataFlow:: Node receiverNode ;
254- string contentType ;
255-
256- StaticContentTypeSetter ( ) { setsStaticContentType ( _, _, this , contentType , receiverNode ) }
257-
258- override string getHeaderName ( ) { result = "content-type" }
259-
260- override string getHeaderValue ( ) { result = contentType }
261-
262- override DataFlow:: Node getName ( ) { none ( ) }
263-
264- override DataFlow:: Node getValue ( ) { none ( ) }
265-
266- override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
267- }
268-
269- /**
270- * Models an HTTP dynamic content-type setter for package: clevergo.tech/clevergo@v0.5.2
271- */
272- private class DynamicContentTypeSetter extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
273- DataFlow:: Node receiverNode ;
274- DataFlow:: Node contentType ;
275-
276- DynamicContentTypeSetter ( ) { setsDynamicContentType ( _, _, this , contentType , receiverNode ) }
277-
278- override string getHeaderName ( ) { result = "content-type" }
279-
280- override DataFlow:: Node getName ( ) { none ( ) }
281-
282- override DataFlow:: Node getValue ( ) { result = contentType }
283-
284- override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
285- }
286-
287- // Holds for a call that sets the body.
288- private predicate setsBody (
289- string package , string receiverName , DataFlow:: Node receiverNode , DataFlow:: Node bodyNode
290- ) {
291- exists ( string methodName , Method m , DataFlow:: CallNode bodySetterCall |
292- m .hasQualifiedName ( package , receiverName , methodName ) and
293- bodySetterCall = m .getACall ( ) and
294- receiverNode = bodySetterCall .getReceiver ( )
295- |
296- package = packagePath ( ) and
297- (
298- // Receiver type: Context
299- receiverName = "Context" and
300- (
301- // signature: func (*Context).Write(data []byte) (int, error)
302- methodName = "Write" and
303- bodyNode = bodySetterCall .getArgument ( 0 )
304- or
305- // signature: func (*Context).WriteString(data string) (int, error)
306- methodName = "WriteString" and
307- bodyNode = bodySetterCall .getArgument ( 0 )
308- )
309- )
310- )
311- }
312-
313- // Holds for a call that sets the body; the content-type is static and implicit.
214+ // Holds for a call that sets the body; the content-type is implicitly set.
314215 private predicate setsBodyAndStaticContentType (
315216 string package , string receiverName , DataFlow:: Node bodyNode , string contentTypeString ,
316217 DataFlow:: Node receiverNode
317218 ) {
318- // One call sets both body and content-type (which is implicit in the func name).
319- exists ( string methodName , Method m , DataFlow:: CallNode bodySetterCall |
320- m .hasQualifiedName ( package , receiverName , methodName ) and
321- bodySetterCall = m .getACall ( ) and
219+ exists ( string methodName , Method met , DataFlow:: CallNode bodySetterCall |
220+ met .hasQualifiedName ( package , receiverName , methodName ) and
221+ bodySetterCall = met .getACall ( ) and
322222 receiverNode = bodySetterCall .getReceiver ( )
323223 |
324224 package = packagePath ( ) and
@@ -400,14 +300,33 @@ private module CleverGo {
400300 )
401301 }
402302
303+ /**
304+ * Models HTTP ResponseBody where the content-type can be dynamically set by the caller.
305+ */
306+ private class HttpResponseBodyDynamicContentType extends HTTP:: ResponseBody:: Range {
307+ DataFlow:: Node contentTypeNode ;
308+ DataFlow:: Node receiverNode ;
309+
310+ HttpResponseBodyDynamicContentType ( ) {
311+ exists ( string package , string receiverName |
312+ setsBodyAndDynamicContentType ( package , receiverName , this , contentTypeNode , receiverNode )
313+ )
314+ }
315+
316+ override DataFlow:: Node getAContentTypeNode ( ) { result = contentTypeNode }
317+
318+ override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
319+ }
320+
403321 // Holds for a call that sets the body; the content-type is a parameter.
322+ // Both body and content-type are parameters in the same func call.
404323 private predicate setsBodyAndDynamicContentType (
405324 string package , string receiverName , DataFlow:: Node bodyNode , DataFlow:: Node contentTypeNode ,
406325 DataFlow:: Node receiverNode
407326 ) {
408- exists ( string methodName , Method m , DataFlow:: CallNode bodySetterCall |
409- m .hasQualifiedName ( package , receiverName , methodName ) and
410- bodySetterCall = m .getACall ( ) and
327+ exists ( string methodName , Method met , DataFlow:: CallNode bodySetterCall |
328+ met .hasQualifiedName ( package , receiverName , methodName ) and
329+ bodySetterCall = met .getACall ( ) and
411330 receiverNode = bodySetterCall .getReceiver ( )
412331 |
413332 package = packagePath ( ) and
@@ -429,14 +348,109 @@ private module CleverGo {
429348 )
430349 }
431350
351+ /**
352+ * Models HTTP ResponseBody where only the body is set.
353+ */
354+ private class HttpResponseBodyNoContentType extends HTTP:: ResponseBody:: Range {
355+ DataFlow:: Node receiverNode ;
356+
357+ HttpResponseBodyNoContentType ( ) {
358+ exists ( string package , string receiverName |
359+ setsBody ( package , receiverName , receiverNode , this )
360+ )
361+ }
362+
363+ override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
364+ }
365+
366+ // Holds for a call that sets the body. The content-type is not defined.
367+ private predicate setsBody (
368+ string package , string receiverName , DataFlow:: Node receiverNode , DataFlow:: Node bodyNode
369+ ) {
370+ exists ( string methodName , Method met , DataFlow:: CallNode bodySetterCall |
371+ met .hasQualifiedName ( package , receiverName , methodName ) and
372+ bodySetterCall = met .getACall ( ) and
373+ receiverNode = bodySetterCall .getReceiver ( )
374+ |
375+ package = packagePath ( ) and
376+ (
377+ // Receiver type: Context
378+ receiverName = "Context" and
379+ (
380+ // signature: func (*Context).Write(data []byte) (int, error)
381+ methodName = "Write" and
382+ bodyNode = bodySetterCall .getArgument ( 0 )
383+ or
384+ // signature: func (*Context).WriteString(data string) (int, error)
385+ methodName = "WriteString" and
386+ bodyNode = bodySetterCall .getArgument ( 0 )
387+ )
388+ )
389+ )
390+ }
391+
392+ /**
393+ * Models HTTP header writer models for package: clevergo.tech/clevergo@v0.5.2
394+ */
395+ private class HeaderWrite extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
396+ string receiverName ;
397+ string methodName ;
398+ DataFlow:: Node headerNameNode ;
399+ DataFlow:: Node headerValueNode ;
400+
401+ HeaderWrite ( ) {
402+ (
403+ // Type methods:
404+ this =
405+ any ( Method m | m .hasQualifiedName ( packagePath ( ) , receiverName , methodName ) ) .getACall ( ) and
406+ (
407+ // Receiver type: Context
408+ receiverName = "Context" and
409+ (
410+ // signature: func (*Context).SetHeader(key string, value string)
411+ methodName = "SetHeader" and
412+ headerNameNode = this .getArgument ( 0 ) and
413+ headerValueNode = this .getArgument ( 1 )
414+ )
415+ )
416+ )
417+ }
418+
419+ override DataFlow:: Node getName ( ) { result = headerNameNode }
420+
421+ override DataFlow:: Node getValue ( ) { result = headerValueNode }
422+
423+ override HTTP:: ResponseWriter getResponseWriter ( ) { none ( ) }
424+ }
425+
426+ /**
427+ * Models an HTTP static content-type setter.
428+ */
429+ private class StaticContentTypeSetter extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
430+ DataFlow:: Node receiverNode ;
431+ string contentTypeString ;
432+
433+ StaticContentTypeSetter ( ) { setsStaticContentType ( _, _, this , contentTypeString , receiverNode ) }
434+
435+ override string getHeaderName ( ) { result = "content-type" }
436+
437+ override string getHeaderValue ( ) { result = contentTypeString }
438+
439+ override DataFlow:: Node getName ( ) { none ( ) }
440+
441+ override DataFlow:: Node getValue ( ) { none ( ) }
442+
443+ override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
444+ }
445+
432446 // Holds for a call that sets the content-type (implicit).
433447 private predicate setsStaticContentType (
434448 string package , string receiverName , DataFlow:: CallNode contentTypeSetterCall ,
435- string contentType , DataFlow:: Node receiverNode
449+ string contentTypeString , DataFlow:: Node receiverNode
436450 ) {
437- exists ( string methodName , Method m |
438- m .hasQualifiedName ( package , receiverName , methodName ) and
439- contentTypeSetterCall = m .getACall ( ) and
451+ exists ( string methodName , Method met |
452+ met .hasQualifiedName ( package , receiverName , methodName ) and
453+ contentTypeSetterCall = met .getACall ( ) and
440454 receiverNode = contentTypeSetterCall .getReceiver ( )
441455 |
442456 package = packagePath ( ) and
@@ -446,32 +460,52 @@ private module CleverGo {
446460 (
447461 // signature: func (*Context).SetContentTypeHTML()
448462 methodName = "SetContentTypeHTML" and
449- contentType = "text/html"
463+ contentTypeString = "text/html"
450464 or
451465 // signature: func (*Context).SetContentTypeJSON()
452466 methodName = "SetContentTypeJSON" and
453- contentType = "application/json"
467+ contentTypeString = "application/json"
454468 or
455469 // signature: func (*Context).SetContentTypeText()
456470 methodName = "SetContentTypeText" and
457- contentType = "text/plain"
471+ contentTypeString = "text/plain"
458472 or
459473 // signature: func (*Context).SetContentTypeXML()
460474 methodName = "SetContentTypeXML" and
461- contentType = "text/xml"
475+ contentTypeString = "text/xml"
462476 )
463477 )
464478 )
465479 }
466480
481+ /**
482+ * Models an HTTP dynamic content-type setter.
483+ */
484+ private class DynamicContentTypeSetter extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
485+ DataFlow:: Node receiverNode ;
486+ DataFlow:: Node contentTypeNode ;
487+
488+ DynamicContentTypeSetter ( ) { setsDynamicContentType ( _, _, this , contentTypeNode , receiverNode ) }
489+
490+ override string getHeaderName ( ) { result = "content-type" }
491+
492+ override string getHeaderValue ( ) { none ( ) }
493+
494+ override DataFlow:: Node getName ( ) { none ( ) }
495+
496+ override DataFlow:: Node getValue ( ) { result = contentTypeNode }
497+
498+ override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = receiverNode }
499+ }
500+
467501 // Holds for a call that sets the content-type via a parameter.
468502 private predicate setsDynamicContentType (
469503 string package , string receiverName , DataFlow:: CallNode contentTypeSetterCall ,
470504 DataFlow:: Node contentTypeNode , DataFlow:: Node receiverNode
471505 ) {
472- exists ( string methodName , Method m |
473- m .hasQualifiedName ( package , receiverName , methodName ) and
474- contentTypeSetterCall = m .getACall ( ) and
506+ exists ( string methodName , Method met |
507+ met .hasQualifiedName ( package , receiverName , methodName ) and
508+ contentTypeSetterCall = met .getACall ( ) and
475509 receiverNode = contentTypeSetterCall .getReceiver ( )
476510 |
477511 package = packagePath ( ) and
@@ -486,21 +520,4 @@ private module CleverGo {
486520 )
487521 )
488522 }
489-
490- /**
491- * Models a HTTP header writer model for package: clevergo.tech/clevergo@v0.5.2
492- */
493- private class HeaderWrite extends HTTP:: HeaderWrite:: Range , DataFlow:: CallNode {
494- HeaderWrite ( ) {
495- // Receiver type: Context
496- // signature: func (*Context).SetHeader(key string, value string)
497- this = any ( Method m | m .hasQualifiedName ( packagePath ( ) , "Context" , "SetHeader" ) ) .getACall ( )
498- }
499-
500- override DataFlow:: Node getName ( ) { result = this .getArgument ( 0 ) }
501-
502- override DataFlow:: Node getValue ( ) { result = this .getArgument ( 1 ) }
503-
504- override HTTP:: ResponseWriter getResponseWriter ( ) { result .getANode ( ) = this .getReceiver ( ) }
505- }
506523}
0 commit comments