@@ -15,7 +15,6 @@ private import semmle.code.java.security.QueryInjection
1515private  import  semmle.code.java.security.RequestForgery
1616private  import  semmle.code.java.dataflow.internal.ModelExclusions as  ModelExclusions
1717private  import  AutomodelJavaUtil as  AutomodelJavaUtil
18- private  import  AutomodelSharedGetCallable as  AutomodelSharedGetCallable
1918import  AutomodelSharedCharacteristics as  SharedCharacteristics
2019import  AutomodelEndpointTypes as  AutomodelEndpointTypes
2120
@@ -84,7 +83,7 @@ abstract class FrameworkModeEndpoint extends TFrameworkModeEndpoint {
8483 /** 
8584 * Returns the callable that contains the endpoint. 
8685 */ 
87-  abstract  Callable  getEnclosingCallable ( ) ;
86+  abstract  Callable  getCallable ( ) ;
8887
8988 abstract  Top  asTop ( ) ;
9089
@@ -106,7 +105,7 @@ class ExplicitParameterEndpoint extends FrameworkModeEndpoint, TExplicitParamete
106105
107106 override  string  getParamName ( )  {  result  =  param .getName ( )  } 
108107
109-  override  Callable  getEnclosingCallable ( )  {  result  =  param .getCallable ( )  } 
108+  override  Callable  getCallable ( )  {  result  =  param .getCallable ( )  } 
110109
111110 override  Top  asTop ( )  {  result  =  param  } 
112111
@@ -126,7 +125,7 @@ class QualifierEndpoint extends FrameworkModeEndpoint, TQualifier {
126125
127126 override  string  getParamName ( )  {  result  =  "this"  } 
128127
129-  override  Callable  getEnclosingCallable ( )  {  result  =  callable  } 
128+  override  Callable  getCallable ( )  {  result  =  callable  } 
130129
131130 override  Top  asTop ( )  {  result  =  callable  } 
132131
@@ -144,7 +143,7 @@ class ReturnValue extends FrameworkModeEndpoint, TReturnValue {
144143
145144 override  string  getParamName ( )  {  none ( )  } 
146145
147-  override  Callable  getEnclosingCallable ( )  {  result  =  callable  } 
146+  override  Callable  getCallable ( )  {  result  =  callable  } 
148147
149148 override  Top  asTop ( )  {  result  =  callable  } 
150149
@@ -163,7 +162,7 @@ class OverridableParameter extends FrameworkModeEndpoint, TOverridableParameter
163162
164163 override  string  getParamName ( )  {  result  =  param .getName ( )  } 
165164
166-  override  Callable  getEnclosingCallable ( )  {  result  =  method  } 
165+  override  Callable  getCallable ( )  {  result  =  method  } 
167166
168167 override  Top  asTop ( )  {  result  =  param  } 
169168
@@ -181,7 +180,7 @@ class OverridableQualifier extends FrameworkModeEndpoint, TOverridableQualifier
181180
182181 override  string  getParamName ( )  {  result  =  "this"  } 
183182
184-  override  Callable  getEnclosingCallable ( )  {  result  =  m  } 
183+  override  Callable  getCallable ( )  {  result  =  m  } 
185184
186185 override  Top  asTop ( )  {  result  =  m  } 
187186
@@ -202,7 +201,9 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
202201
203202 class  EndpointType  =  AutomodelEndpointTypes:: EndpointType ;
204203
205-  class  NegativeEndpointType  =  AutomodelEndpointTypes:: NegativeSinkType ;
204+  class  SinkType  =  AutomodelEndpointTypes:: SinkType ;
205+ 
206+  class  SourceType  =  AutomodelEndpointTypes:: SourceType ;
206207
207208 class  RelatedLocation  =  Location:: Top ;
208209
@@ -244,8 +245,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
244245 additional  predicate  sinkSpec ( 
245246 Endpoint  e ,  string  package ,  string  type ,  string  name ,  string  signature ,  string  ext ,  string  input 
246247 )  { 
247-  e .getEnclosingCallable ( ) .hasQualifiedName ( package ,  type ,  name )  and 
248-  signature  =  ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) )  and 
248+  e .getCallable ( ) .hasQualifiedName ( package ,  type ,  name )  and 
249+  signature  =  ExternalFlow:: paramsString ( e .getCallable ( ) )  and 
249250 ext  =  ""  and 
250251 input  =  e .getMaDInput ( ) 
251252 } 
@@ -254,8 +255,8 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
254255 Endpoint  e ,  string  package ,  string  type ,  string  name ,  string  signature ,  string  ext , 
255256 string  output 
256257 )  { 
257-  e .getEnclosingCallable ( ) .hasQualifiedName ( package ,  type ,  name )  and 
258-  signature  =  ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) )  and 
258+  e .getCallable ( ) .hasQualifiedName ( package ,  type ,  name )  and 
259+  signature  =  ExternalFlow:: paramsString ( e .getCallable ( ) )  and 
259260 ext  =  ""  and 
260261 output  =  e .getMaDOutput ( ) 
261262 } 
@@ -267,10 +268,10 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
267268 */ 
268269 RelatedLocation  getRelatedLocation ( Endpoint  e ,  RelatedLocationType  type )  { 
269270 type  =  MethodDoc ( )  and 
270-  result  =  e .getEnclosingCallable ( ) .( Documentable ) .getJavadoc ( ) 
271+  result  =  e .getCallable ( ) .( Documentable ) .getJavadoc ( ) 
271272 or 
272273 type  =  ClassDoc ( )  and 
273-  result  =  e .getEnclosingCallable ( ) .getDeclaringType ( ) .( Documentable ) .getJavadoc ( ) 
274+  result  =  e .getCallable ( ) .getDeclaringType ( ) .( Documentable ) .getJavadoc ( ) 
274275 } 
275276} 
276277
@@ -292,16 +293,27 @@ class FrameworkModeMetadataExtractor extends string {
292293
293294 predicate  hasMetadata ( 
294295 Endpoint  e ,  string  package ,  string  type ,  string  subtypes ,  string  name ,  string  signature , 
295-  string  input ,  string  output ,  string  parameterName 
296+  string  input ,  string  output ,  string  parameterName ,  string  alreadyAiModeled , 
297+  string  extensibleType 
296298 )  { 
297-  ( if  exists ( e .getParamName ( ) )  then  parameterName  =  e .getParamName ( )  else  parameterName  =  "" )  and 
298-  name  =  e .getEnclosingCallable ( ) .getName ( )  and 
299-  ( if  exists ( e .getMaDInput ( ) )  then  input  =  e .getMaDInput ( )  else  input  =  "" )  and 
300-  ( if  exists ( e .getMaDOutput ( ) )  then  output  =  e .getMaDOutput ( )  else  output  =  "" )  and 
301-  package  =  e .getEnclosingCallable ( ) .getDeclaringType ( ) .getPackage ( ) .getName ( )  and 
302-  type  =  e .getEnclosingCallable ( ) .getDeclaringType ( ) .getErasure ( ) .( RefType ) .nestedName ( )  and 
303-  subtypes  =  AutomodelJavaUtil:: considerSubtypes ( e .getEnclosingCallable ( ) ) .toString ( )  and 
304-  signature  =  ExternalFlow:: paramsString ( e .getEnclosingCallable ( ) ) 
299+  exists ( Callable  callable  |  e .getCallable ( )  =  callable  | 
300+  ( if  exists ( e .getMaDInput ( ) )  then  input  =  e .getMaDInput ( )  else  input  =  "" )  and 
301+  ( if  exists ( e .getMaDOutput ( ) )  then  output  =  e .getMaDOutput ( )  else  output  =  "" )  and 
302+  package  =  callable .getDeclaringType ( ) .getPackage ( ) .getName ( )  and 
303+  // we're using the erased types because the MaD convention is to not specify type parameters. 
304+  // Whether something is or isn't a sink doesn't usually depend on the type parameters. 
305+  type  =  callable .getDeclaringType ( ) .getErasure ( ) .( RefType ) .nestedName ( )  and 
306+  subtypes  =  AutomodelJavaUtil:: considerSubtypes ( callable ) .toString ( )  and 
307+  name  =  callable .getName ( )  and 
308+  signature  =  ExternalFlow:: paramsString ( callable )  and 
309+  ( if  exists ( e .getParamName ( ) )  then  parameterName  =  e .getParamName ( )  else  parameterName  =  "" )  and 
310+  e .getExtensibleType ( )  =  extensibleType 
311+  )  and 
312+  ( 
313+  not  CharacteristicsImpl:: isModeled ( e ,  _,  extensibleType ,  _)  and  alreadyAiModeled  =  "" 
314+  or 
315+  CharacteristicsImpl:: isModeled ( e ,  _,  extensibleType ,  alreadyAiModeled ) 
316+  ) 
305317 } 
306318} 
307319
@@ -310,53 +322,79 @@ class FrameworkModeMetadataExtractor extends string {
310322 */ 
311323
312324/** 
313-  * A negative characteristic that indicates that an is-style boolean method is unexploitable even if it is a sink. 
325+  * A negative characteristic that indicates that parameters of an is-style boolean method should not be considered sinks, 
326+  * and its return value should not be considered a source. 
314327 * 
315328 * A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return 
316329 * type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does 
317330 * the dangerous/interesting thing, so we want the latter to be modeled as the sink. 
318331 * 
319332 * TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks 
320333 */ 
321- private  class  UnexploitableIsCharacteristic  extends  CharacteristicsImpl:: NotASinkCharacteristic  { 
334+ private  class  UnexploitableIsCharacteristic  extends  CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic 
335+ { 
322336 UnexploitableIsCharacteristic ( )  {  this  =  "unexploitable (is-style boolean method)"  } 
323337
324338 override  predicate  appliesToEndpoint ( Endpoint  e )  { 
325-  not  FrameworkCandidatesImpl:: isSink ( e ,  _,  _)  and 
326-  e .getEnclosingCallable ( ) .getName ( ) .matches ( "is%" )  and 
327-  e .getEnclosingCallable ( ) .getReturnType ( )  instanceof  BooleanType 
339+  e .getCallable ( ) .getName ( ) .matches ( "is%" )  and 
340+  e .getCallable ( ) .getReturnType ( )  instanceof  BooleanType  and 
341+  ( 
342+  e .getExtensibleType ( )  =  "sinkModel"  and 
343+  not  FrameworkCandidatesImpl:: isSink ( e ,  _,  _) 
344+  or 
345+  e .getExtensibleType ( )  =  "sourceModel"  and 
346+  not  FrameworkCandidatesImpl:: isSource ( e ,  _,  _)  and 
347+  e .getMaDOutput ( )  =  "ReturnValue" 
348+  ) 
328349 } 
329350} 
330351
331352/** 
332-  * A negative characteristic that indicates that an existence-checking boolean method is unexploitable even if it is a  
333-  * sink . 
353+  * A negative characteristic that indicates that parameters of  an existence-checking boolean method should not be  
354+  * considered sinks, and its return value should not be considered a source . 
334355 * 
335356 * A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a 
336357 * boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the 
337358 * dangerous/interesting thing, so we want the latter to be modeled as the sink. 
338359 */ 
339- private  class  UnexploitableExistsCharacteristic  extends  CharacteristicsImpl:: NotASinkCharacteristic  { 
360+ private  class  UnexploitableExistsCharacteristic  extends  CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic 
361+ { 
340362 UnexploitableExistsCharacteristic ( )  {  this  =  "unexploitable (existence-checking boolean method)"  } 
341363
342364 override  predicate  appliesToEndpoint ( Endpoint  e )  { 
343-  not  FrameworkCandidatesImpl:: isSink ( e ,  _,  _)  and 
344365 exists ( Callable  callable  | 
345-  callable  =  e .getEnclosingCallable ( )  and 
366+  callable  =  e .getCallable ( )  and 
346367 callable .getName ( ) .toLowerCase ( )  =  [ "exists" ,  "notexists" ]  and 
347368 callable .getReturnType ( )  instanceof  BooleanType 
369+  | 
370+  e .getExtensibleType ( )  =  "sinkModel"  and 
371+  not  FrameworkCandidatesImpl:: isSink ( e ,  _,  _) 
372+  or 
373+  e .getExtensibleType ( )  =  "sourceModel"  and 
374+  not  FrameworkCandidatesImpl:: isSource ( e ,  _,  _)  and 
375+  e .getMaDOutput ( )  =  "ReturnValue" 
348376 ) 
349377 } 
350378} 
351379
352380/** 
353-  * A negative characteristic that indicates that an endpoint is an argument to an exception, which is not a sink. 
381+  * A negative characteristic that indicates that parameters of an exception method or constructor should not be considered sinks, 
382+  * and its return value should not be considered a source. 
354383 */ 
355- private  class  ExceptionCharacteristic  extends  CharacteristicsImpl:: NotASinkCharacteristic  { 
384+ private  class  ExceptionCharacteristic  extends  CharacteristicsImpl:: NeitherSourceNorSinkCharacteristic 
385+ { 
356386 ExceptionCharacteristic ( )  {  this  =  "exception"  } 
357387
358388 override  predicate  appliesToEndpoint ( Endpoint  e )  { 
359-  e .getEnclosingCallable ( ) .getDeclaringType ( ) .getASupertype * ( )  instanceof  TypeThrowable 
389+  e .getCallable ( ) .getDeclaringType ( ) .getASupertype * ( )  instanceof  TypeThrowable  and 
390+  ( 
391+  e .getExtensibleType ( )  =  "sinkModel"  and 
392+  not  FrameworkCandidatesImpl:: isSink ( e ,  _,  _) 
393+  or 
394+  e .getExtensibleType ( )  =  "sourceModel"  and 
395+  not  FrameworkCandidatesImpl:: isSource ( e ,  _,  _)  and 
396+  e .getMaDOutput ( )  =  "ReturnValue" 
397+  ) 
360398 } 
361399} 
362400
@@ -368,6 +406,6 @@ private class NotAModelApi extends CharacteristicsImpl::UninterestingToModelChar
368406 NotAModelApi ( )  {  this  =  "not a model API"  } 
369407
370408 override  predicate  appliesToEndpoint ( Endpoint  e )  { 
371-  not  e .getEnclosingCallable ( )  instanceof  ModelExclusions:: ModelApi 
409+  not  e .getCallable ( )  instanceof  ModelExclusions:: ModelApi 
372410 } 
373411} 
0 commit comments