Skip to content

Commit 6920430

Browse files
committed
Improve dependency injection through import function calls
1 parent 9019879 commit 6920430

File tree

6 files changed

+62
-12
lines changed

6 files changed

+62
-12
lines changed

javascript/ql/lib/semmle/javascript/frameworks/Nest.qll

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -510,15 +510,36 @@ module NestJS {
510510
* ```
511511
*/
512512
private DataFlow::Node providerTuple() {
513-
result =
514-
DataFlow::moduleImport("@nestjs/common")
515-
.getAPropertyRead("Module")
516-
.getACall()
517-
.getOptionArgument(0, "providers")
518-
.getALocalSource()
519-
.(DataFlow::ArrayCreationNode)
520-
.getAnElement()
513+
exists(DataFlow::CallNode moduleCall |
514+
moduleCall = DataFlow::moduleImport("@nestjs/common").getAPropertyRead("Module").getACall() and
515+
result = providerTupleAux(moduleCall.getArgument(0).getALocalSource())
516+
)
517+
}
518+
519+
private DataFlow::Node providerTupleAux(DataFlow::ObjectLiteralNode o) {
520+
(
521+
result =
522+
o.getAPropertyWrite("providers")
523+
.getRhs()
524+
.getALocalSource()
525+
.(DataFlow::ArrayCreationNode)
526+
.getAnElement()
527+
or
528+
result =
529+
providerTupleAux(o.getAPropertyWrite("imports")
530+
.getRhs()
531+
.getALocalSource()
532+
.(DataFlow::ArrayCreationNode)
533+
.getAnElement()
534+
.(DataFlow::CallNode)
535+
.getCalleeNode()
536+
.getAFunctionValue()
537+
.getFunction()
538+
.getAReturnedExpr()
539+
.flow())
540+
)
521541
}
542+
522543
private DataFlow::Node getConcreteClassFromProviderTuple(DataFlow::SourceNode tuple) {
523544
result = tuple.getAPropertyWrite("useClass").getRhs()
524545
or

javascript/ql/test/library-tests/frameworks/Nest/global/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Module } from '@nestjs/common';
22
import { Controller } from './validation';
3+
import { Imports } from './imports';
34
import { Foo, Foo2, Foo3 } from './foo.interface';
45
import { FooImpl, Foo2Impl, Foo3Impl } from './foo.impl';
56

67
const foo3 = new Foo3Impl()
78

89
@Module({
910
controllers: [Controller],
11+
imports: [Imports.forRoot()],
1012
providers: [
1113
{
1214
provide: Foo,

javascript/ql/test/library-tests/frameworks/Nest/global/foo.impl.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Foo , Foo2 } from "./foo.interface";
1+
import { Foo, Foo2, Foo3, Foo4 } from "./foo.interface";
22

33
export class FooImpl extends Foo {
44
fooMethod(x: string) {
@@ -12,7 +12,13 @@ export class Foo2Impl extends Foo2 {
1212
}
1313
}
1414

15-
export class Foo3Impl extends Foo2 {
15+
export class Foo3Impl extends Foo3 {
16+
fooMethod(x: string) {
17+
sink(x); // $ hasValueFlow=x
18+
}
19+
}
20+
21+
export class Foo4Impl extends Foo4 {
1622
fooMethod(x: string) {
1723
sink(x); // $ hasValueFlow=x
1824
}

javascript/ql/test/library-tests/frameworks/Nest/global/foo.interface.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ export abstract class Foo2 {
99
export abstract class Foo3 {
1010
abstract fooMethod(x: string): void;
1111
}
12+
13+
export abstract class Foo4 {
14+
abstract fooMethod(x: string): void;
15+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { DynamicModule } from '@nestjs/common';
2+
import { Foo4Impl } from './foo.impl';
3+
import { Foo4 } from './foo.interface';
4+
5+
export class Imports {
6+
static forRoot(): DynamicModule {
7+
return {
8+
providers: [
9+
{
10+
provide: Foo4,
11+
useClass: Foo4Impl,
12+
},
13+
],
14+
};
15+
}
16+
}

javascript/ql/test/library-tests/frameworks/Nest/global/validation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Get, Query } from '@nestjs/common';
22
import { IsIn } from 'class-validator';
3-
import { Foo, Foo2, Foo3 } from './foo.interface';
3+
import { Foo, Foo2, Foo3, Foo4 } from './foo.interface';
44

55
export class Controller {
66
constructor(
7-
private readonly foo: Foo, private readonly foo2: Foo2, private readonly foo3: Foo3
7+
private readonly foo: Foo, private readonly foo2: Foo2, private readonly foo3: Foo3, private readonly foo4: Foo4
88
) { }
99

1010
@Get()
@@ -18,6 +18,7 @@ export class Controller {
1818
this.foo.fooMethod(x);
1919
this.foo2.fooMethod(x);
2020
this.foo3.fooMethod(x);
21+
this.foo4.fooMethod(x);
2122
}
2223
}
2324

0 commit comments

Comments
 (0)