@@ -317,4 +317,96 @@ module Internal {
317317
318318 }
319319
320+ /**
321+ * A test for the value of a `typeof` expression.
322+ */
323+ private class TypeofTest extends EqualityTest {
324+ Expr operand ;
325+
326+ TypeofTag tag ;
327+
328+ TypeofTest ( ) {
329+ exists ( Expr op1 , Expr op2 |
330+ hasOperands ( op1 , op2 ) |
331+ operand = op1 .( TypeofExpr ) .getOperand ( ) and
332+ op2 .mayHaveStringValue ( tag )
333+ )
334+ }
335+
336+ boolean getTheTestResult ( ) {
337+ exists ( boolean testResult |
338+ testResult = true and operand .analyze ( ) .getTheType ( ) .getTypeofTag ( ) = tag or
339+ testResult = false and not operand .analyze ( ) .getAType ( ) .getTypeofTag ( ) = tag |
340+ if getPolarity ( ) = true then
341+ result = testResult
342+ else
343+ result = testResult .booleanNot ( )
344+ )
345+ }
346+
347+ /**
348+ * Gets the operand used in the `typeof` expression.
349+ */
350+ Expr getOperand ( ) {
351+ result = operand
352+ }
353+
354+ /**
355+ * Gets the `typeof` tag that is tested.
356+ */
357+ TypeofTag getTag ( ) {
358+ result = tag
359+ }
360+ }
361+
362+ /**
363+ * A defensive expression that tests if an expression has type `function`.
364+ */
365+ private class FunctionTypeGuard extends DefensiveExpression {
366+
367+ TypeofTest test ;
368+
369+ boolean polarity ;
370+
371+ FunctionTypeGuard ( ) {
372+ exists ( Expr guard , VarRef guardVar , VarRef useVar |
373+ this = guard .flow ( ) and
374+ test = stripNotsAndParens ( guard , polarity ) and
375+ test .getOperand ( ) = guardVar and
376+ guardVar .getVariable ( ) = useVar .getVariable ( ) |
377+ getAGuardedExpr ( guard ) .stripParens ( ) .( NonFunctionCallCrashUse ) .getVulnerableSubexpression ( ) = useVar
378+ ) and
379+ test .getTag ( ) = "function"
380+ }
381+
382+ override boolean getTheTestResult ( ) {
383+ polarity = true and result = test .getTheTestResult ( )
384+ or
385+ polarity = false and result = test .getTheTestResult ( ) .booleanNot ( )
386+ }
387+
388+ }
389+
390+ /**
391+ * A test for `undefined` using a `typeof` expression.
392+ */
393+ private class TypeofUndefinedTest extends UndefinedNullTest {
394+
395+ TypeofTest test ;
396+
397+ TypeofUndefinedTest ( ) {
398+ this = test and
399+ test .getTag ( ) = "undefined"
400+ }
401+
402+ override boolean getTheTestResult ( ) {
403+ result = test .getTheTestResult ( )
404+ }
405+
406+ override Expr getOperand ( ) {
407+ result = test .getOperand ( )
408+ }
409+
410+ }
411+
320412}
0 commit comments