From 4673e4778b682fb25acd0f2d44607d9826bc86f5 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 2 Dec 2025 14:42:51 +0100 Subject: [PATCH] JS: Fix bad join in export logic --- .../lib/semmle/javascript/ES2015Modules.qll | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index 9f37e3082b89..4959a8c3b041 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -29,6 +29,7 @@ class ES2015Module extends Module { override string getName() { result = this.getFile().getStem() } /** Gets an export declaration in this module. */ + pragma[nomagic] ExportDeclaration getAnExport() { result.getTopLevel() = this } overlay[global] @@ -38,6 +39,7 @@ class ES2015Module extends Module { /** Holds if this module exports variable `v` under the name `name`. */ overlay[global] + pragma[nomagic] predicate exportsAs(LexicalName v, string name) { this.getAnExport().exportsAs(v, name) } override predicate isStrict() { @@ -345,6 +347,7 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { /** Holds if this export declaration exports variable `v` under the name `name`. */ overlay[global] + pragma[nomagic] final predicate exportsAs(LexicalName v, string name) { this.exportsDirectlyAs(v, name) or @@ -821,18 +824,31 @@ class SelectiveReExportDeclaration extends ReExportDeclaration, ExportNamedDecla result = ExportNamedDeclaration.super.getImportedPath() } + overlay[global] + pragma[nomagic] + private predicate reExportsFrom(ES2015Module mod, string originalName, string reExportedName) { + exists(ExportSpecifier spec | + spec = this.getASpecifier() and + reExportedName = spec.getExportedName() and + originalName = spec.getLocalName() and + mod = this.getReExportedES2015Module() + ) + } + overlay[global] override predicate reExportsAs(LexicalName v, string name) { - exists(ExportSpecifier spec | spec = this.getASpecifier() and name = spec.getExportedName() | - this.getReExportedES2015Module().exportsAs(v, spec.getLocalName()) + exists(ES2015Module mod, string originalName | + this.reExportsFrom(mod, originalName, name) and + mod.exportsAs(v, originalName) ) and not (this.isTypeOnly() and v instanceof Variable) } overlay[global] override DataFlow::Node getReExportedSourceNode(string name) { - exists(ExportSpecifier spec | spec = this.getASpecifier() and name = spec.getExportedName() | - result = this.getReExportedES2015Module().getAnExport().getSourceNode(spec.getLocalName()) + exists(ES2015Module mod, string originalName | + this.reExportsFrom(mod, originalName, name) and + result = mod.getAnExport().getSourceNode(originalName) ) } }