@@ -263,4 +263,84 @@ module TypeResolution {
263263 typeMember ( host , contents .getAReadContent ( ) , type )
264264 )
265265 }
266+
267+ signature predicate nodeSig ( Node node ) ;
268+
269+ /**
270+ * Tracks types that have a certain property, in the sense that:
271+ * - an intersection type has the property if any member has the property
272+ * - a union type has the property if all its members have the property
273+ */
274+ module TrackMustProp< nodeSig / 1 directlyHasProperty> {
275+ predicate hasProperty ( Node node ) {
276+ directlyHasProperty ( node )
277+ or
278+ exists ( Node mid |
279+ hasProperty ( mid ) and
280+ TypeFlow:: step ( mid , node )
281+ )
282+ or
283+ unionHasProp ( node )
284+ or
285+ hasProperty ( node .( IntersectionTypeExpr ) .getAnElementType ( ) )
286+ or
287+ exists ( ConditionalTypeExpr cond |
288+ node = cond and
289+ hasProperty ( cond .getTrueType ( ) ) and
290+ hasProperty ( cond .getFalseType ( ) )
291+ )
292+ }
293+
294+ private predicate unionHasProp ( UnionTypeExpr node , int n ) {
295+ hasProperty ( node .getElementType ( 0 ) ) and n = 1
296+ or
297+ unionHasProp ( node , n - 1 ) and
298+ hasProperty ( node .getElementType ( n - 1 ) )
299+ }
300+
301+ private predicate unionHasProp ( UnionTypeExpr node ) {
302+ unionHasProp ( node , node .getNumElementType ( ) )
303+ }
304+ }
305+
306+ private predicate isSanitizingPrimitiveTypeBase ( Node node ) {
307+ node .( TypeExpr ) .isNumbery ( )
308+ or
309+ node .( TypeExpr ) .isBooleany ( )
310+ or
311+ node .( TypeExpr ) .isNull ( )
312+ or
313+ node .( TypeExpr ) .isUndefined ( )
314+ or
315+ node .( TypeExpr ) .isVoid ( )
316+ or
317+ node .( TypeExpr ) .isNever ( )
318+ or
319+ node instanceof LiteralTypeExpr
320+ or
321+ node = any ( EnumMember m ) .getIdentifier ( ) // enum members are constant
322+ or
323+ node instanceof EnumDeclaration // enums are unions of constants
324+ }
325+
326+ /**
327+ * Holds if `node` refers to a type that is considered untaintable (if actually enforced at runtime).
328+ *
329+ * Specifically, the types `number`, `boolean`, `null`, `undefined`, `void`, `never`, as well as literal types (`"foo"`)
330+ * and enums and enum members have this property.
331+ */
332+ predicate isSanitizingPrimitiveType =
333+ TrackMustProp< isSanitizingPrimitiveTypeBase / 1 > :: hasProperty / 1 ;
334+
335+ /**
336+ * Holds if `value` has a type that is considered untaintable (if actually enforced at runtime).
337+ *
338+ * See `isSanitizingPrimitiveType`.
339+ */
340+ predicate valueHasSanitizingPrimitiveType ( Node value ) {
341+ exists ( Node type |
342+ valueHasType ( value , type ) and
343+ isSanitizingPrimitiveType ( type )
344+ )
345+ }
266346}
0 commit comments