NestJS dependency Injection support useFactory provider

This commit is contained in:
Vasco-jofra
2025-06-15 00:09:07 +02:00
parent baf0d3ef22
commit 2b143c86ac
6 changed files with 37 additions and 11 deletions

View File

@@ -519,12 +519,20 @@ module NestJS {
.(DataFlow::ArrayCreationNode)
.getAnElement()
}
private DataFlow::Node getConcreteClassFromProviderTuple(DataFlow::SourceNode tuple) {
result = tuple.getAPropertyWrite("useClass").getRhs()
or
exists(DataFlow::FunctionNode f |
f = tuple.getAPropertyWrite("useFactory").getRhs().getALocalSource() and
result.getAstNode() = f.getFunction().getAReturnedExpr().getType().(ClassType).getClass()
)
}
private predicate providerPair(DataFlow::Node interface, DataFlow::Node concreteClass) {
exists(DataFlow::SourceNode tuple |
tuple = providerTuple().getALocalSource() and
interface = tuple.getAPropertyWrite("provide").getRhs() and
concreteClass = tuple.getAPropertyWrite("useClass").getRhs()
concreteClass = getConcreteClassFromProviderTuple(tuple)
)
}

View File

@@ -1,12 +1,19 @@
import { Module } from '@nestjs/common';
import { Controller } from './validation';
import { Foo } from './foo.interface';
import { FooImpl } from './foo.impl';
import { Foo, Foo2 } from './foo.interface';
import { FooImpl, Foo2Impl } from './foo.impl';
@Module({
controllers: [Controller],
providers: [{
provide: Foo, useClass: FooImpl
}],
controllers: [Controller],
providers: [
{
provide: Foo,
useClass: FooImpl
},
{
provide: Foo2,
useFactory: () => new Foo2Impl()
}
],
})
export class AppModule { }

View File

@@ -1,7 +1,13 @@
import { Foo } from "./foo.interface";
import { Foo , Foo2 } from "./foo.interface";
export class FooImpl extends Foo {
fooMethod(x: string) {
sink(x); // $ hasValueFlow=x
}
}
export class Foo2Impl extends Foo2 {
fooMethod(x: string) {
sink(x); // $ hasValueFlow=x
}
}

View File

@@ -1,3 +1,7 @@
export abstract class Foo {
abstract fooMethod(x: string): void;
}
export abstract class Foo2 {
abstract fooMethod(x: string): void;
}

View File

@@ -1,10 +1,10 @@
import { Get, Query } from '@nestjs/common';
import { IsIn } from 'class-validator';
import { Foo } from './foo.interface';
import { Foo, Foo2 } from './foo.interface';
export class Controller {
constructor(
private readonly foo: Foo
private readonly foo: Foo, private readonly foo2: Foo2
) { }
@Get()
@@ -16,6 +16,7 @@ export class Controller {
@Get()
route2(@Query('x') x: string) {
this.foo.fooMethod(x);
this.foo2.fooMethod(x);
}
}

View File

@@ -1,7 +1,7 @@
testFailures
routeHandler
| global/validation.ts:11:3:14:3 | route1( ... OK\\n } |
| global/validation.ts:17:3:19:3 | route2( ... x);\\n } |
| global/validation.ts:17:3:20:3 | route2( ... x);\\n } |
| local/customDecorator.ts:18:3:20:3 | sneaky( ... OK\\n } |
| local/customDecorator.ts:23:3:25:3 | safe(@S ... OK\\n } |
| local/customPipe.ts:20:5:22:5 | sanitiz ... K\\n } |