@@ -188,7 +188,7 @@ module NameResolution {
188188 private predicate commonStep ( Node node1 , Node node2 ) {
189189 commonStep1 ( node1 , node2 )
190190 or
191- node2 = ValueFlow :: exportsObjectRhs ( node1 )
191+ node2 = exportsObjectRhs ( node1 )
192192 }
193193
194194 /**
@@ -216,7 +216,8 @@ module NameResolution {
216216 exists ( PropAccess access |
217217 node1 = access .getBase ( ) and
218218 name = access .getPropertyName ( ) and
219- node2 = access
219+ node2 = access and
220+ access instanceof RValue
220221 )
221222 or
222223 exists ( ObjectPattern pattern |
@@ -268,6 +269,66 @@ module NameResolution {
268269 )
269270 }
270271
272+ pragma [ nomagic]
273+ private GlobalVarAccess globalAccess ( Module mod , string name ) {
274+ result .getName ( ) = name and
275+ result .getTopLevel ( ) = mod and
276+ name = [ "exports" , "module" ] // manually restrict size of predicate
277+ }
278+
279+ /** Gets a reference to the CommonJS `module` object within the given module. */
280+ private Node moduleObjectRef ( Module mod ) {
281+ result = mod .getScope ( ) .getVariable ( "module" ) .getAnAccess ( )
282+ or
283+ result = globalAccess ( mod , "module" )
284+ or
285+ commonStep1 ( moduleObjectRef ( mod ) , result )
286+ }
287+
288+ /** Gets the right-hand side of an assignment to `module.exports` within the given module. */
289+ private Node exportsObjectRhs ( Module mod ) {
290+ exists ( AssignExpr assign |
291+ assign .getLhs ( ) .( PropAccess ) .accesses ( moduleObjectRef ( mod ) , "exports" ) and
292+ result = assign .getRhs ( )
293+ )
294+ }
295+
296+ /** Gets a node that is bulk-exported from the given module. */
297+ Node getModuleBulkExport ( ModuleLike mod ) { result = exportsObjectRhs ( mod ) }
298+
299+ /** Gets a node that flows to `module.exports` within the given module. */
300+ private Node exportsObjectRhsPred ( Module mod ) { commonStep1 * ( result , exportsObjectRhs ( mod ) ) }
301+
302+ /** Gets a node that is an alias for `module.exports` within the given module. */
303+ private Node exportsObjectAlias ( Module mod ) {
304+ result = mod .getScope ( ) .getVariable ( "exports" ) .getAnAccess ( )
305+ or
306+ result = globalAccess ( mod , "exports" )
307+ or
308+ result .( ThisExpr ) .getBindingContainer ( ) = mod and
309+ mod instanceof NodeModule
310+ or
311+ readStep ( moduleObjectRef ( mod ) , "exports" , result )
312+ or
313+ result = exportsObjectRhsPred ( mod )
314+ or
315+ commonStep ( exportsObjectAlias ( mod ) , result )
316+ }
317+
318+ /** Holds if `node` is stored into `module.exports.<name>` within the given module. */
319+ private predicate storeToExports ( Node node , Module mod , string name ) {
320+ exists ( AssignExpr assign |
321+ node = assign .getRhs ( ) and
322+ assign .getLhs ( ) .( PropAccess ) .accesses ( exportsObjectAlias ( mod ) , name )
323+ )
324+ or
325+ exists ( Property prop |
326+ node = prop .getInit ( ) and
327+ name = prop .getName ( ) and
328+ prop .getObjectExpr ( ) = exportsObjectAlias ( mod )
329+ )
330+ }
331+
271332 private signature module TypeResolutionInputSig {
272333 /**
273334 * Holds if flow is permitted through the given variable.
@@ -399,58 +460,6 @@ module NameResolution {
399460 value = target .getAnAssignedExpr ( ) .( ObjectExpr ) .getPropertyByName ( prop ) .getInit ( )
400461 }
401462
402- pragma [ nomagic]
403- private GlobalVarAccess globalAccess ( Module mod , string name ) {
404- result .getName ( ) = name and
405- result .getTopLevel ( ) = mod and
406- name = [ "exports" , "module" ] // manually restrict size of predicate
407- }
408-
409- private Node moduleObjectRef ( Module mod ) {
410- result = mod .getScope ( ) .getVariable ( "module" ) .getAnAccess ( )
411- or
412- result = globalAccess ( mod , "module" )
413- or
414- commonStep1 ( moduleObjectRef ( mod ) , result )
415- }
416-
417- Node exportsObjectRhs ( Module mod ) {
418- exists ( AssignExpr assign |
419- assign .getLhs ( ) .( PropAccess ) .accesses ( moduleObjectRef ( mod ) , "exports" ) and
420- result = assign .getRhs ( )
421- )
422- }
423-
424- private Node exportsObjectRhsPred ( Module mod ) { commonStep1 * ( result , exportsObjectRhs ( mod ) ) }
425-
426- private Node exportsObjectAlias ( Module mod ) {
427- result = mod .getScope ( ) .getVariable ( "exports" ) .getAnAccess ( )
428- or
429- result = globalAccess ( mod , "exports" )
430- or
431- result .( ThisExpr ) .getBindingContainer ( ) = mod and
432- mod instanceof NodeModule
433- or
434- readStep ( moduleObjectRef ( mod ) , "exports" , result )
435- or
436- result = exportsObjectRhsPred ( mod )
437- or
438- commonStep ( exportsObjectAlias ( mod ) , result )
439- }
440-
441- private predicate storeToExports ( Node node , Module mod , string name ) {
442- exists ( AssignExpr assign |
443- node = assign .getRhs ( ) and
444- assign .getLhs ( ) .( PropAccess ) .accesses ( exportsObjectAlias ( mod ) , name )
445- )
446- or
447- exists ( Property prop |
448- node = prop .getInit ( ) and
449- name = prop .getName ( ) and
450- prop .getObjectExpr ( ) = exportsObjectAlias ( mod )
451- )
452- }
453-
454463 /** Steps that only apply for this configuration. */
455464 private predicate specificStep ( Node node1 , Node node2 ) {
456465 exists ( LexicalName var | S:: isRelevantVariable ( var ) |
@@ -519,6 +528,8 @@ module NameResolution {
519528 or
520529 defaultImportInteropStep ( trackModule ( mod ) , result ) and
521530 not mod .( ES2015Module ) .hasBothNamedAndDefaultExports ( )
531+ or
532+ result = exportsObjectAlias ( mod )
522533 }
523534
524535 predicate trackClassValue = ValueFlow:: TrackNode< ClassDefinition > :: track / 1 ;
0 commit comments