Skip to content

Commit 91031f8

Browse files
authored
feat(tracer): add follow consecutive assignment of return values (#385)
1 parent 728d744 commit 91031f8

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

.changeset/beige-insects-taste.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@nodesecure/tracer": minor
3+
---
4+
5+
feat(tracer): add follow consecutive assignment of return values

workspaces/tracer/src/VariableTracer.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export class VariableTracer extends EventEmitter {
7878
#traced = new Map<string, Traced>();
7979
#variablesRefToGlobal = new Set<string>();
8080
#neutralCallable = new Set<string>();
81+
#assignedReturnValueToTraced = new Map<string, string>();
8182

8283
debug() {
8384
console.log(this.#traced);
@@ -442,6 +443,9 @@ export class VariableTracer extends EventEmitter {
442443
type: "ReturnValueAssignment",
443444
name: id.name
444445
});
446+
if (tracedVariant.followConsecutiveAssignment) {
447+
this.#assignedReturnValueToTraced.set(id.name, tracedFullIdentifierName);
448+
}
445449
}
446450
// const id = Function.prototype.call.call(require, require, "http");
447451
if (this.#neutralCallable.has(identifierName) || isEvilIdentifierPath(fullIdentifierPath)) {
@@ -489,6 +493,16 @@ export class VariableTracer extends EventEmitter {
489493
this.#variablesRefToGlobal.add(id.name);
490494
}
491495

496+
if (this.#assignedReturnValueToTraced.has(childNode.name)) {
497+
const tracedFullIdentifierName = this.#assignedReturnValueToTraced.get(childNode.name)!;
498+
const tracedVariant = this.#traced.get(tracedFullIdentifierName)!;
499+
tracedVariant.assignmentMemory.push({
500+
type: "ReturnValueAssignment",
501+
name: id.name
502+
});
503+
this.#assignedReturnValueToTraced.set(id.name, tracedFullIdentifierName);
504+
}
505+
492506
break;
493507
}
494508

workspaces/tracer/test/VariableTracer.spec.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,80 @@ test("should be able to trace the return value of a traced function in an array
365365
name: "user"
366366
}]);
367367
});
368+
369+
test("should be able to follow re-assignment on traced return values", () => {
370+
const helpers = createTracer(false);
371+
helpers.tracer.trace("os.userInfo", {
372+
followConsecutiveAssignment: true,
373+
followReturnValueAssignement: true,
374+
moduleName: "os"
375+
});
376+
377+
helpers.walkOnCode(`
378+
import os from "os";
379+
380+
const user = [...os.userInfo()];
381+
const userBis = user;
382+
console.log(userBis);
383+
`);
384+
385+
assert.deepEqual(helpers.tracer.getDataFromIdentifier("os.userInfo")?.assignmentMemory, [{
386+
type: "ReturnValueAssignment",
387+
name: "user"
388+
}, {
389+
type: "ReturnValueAssignment",
390+
name: "userBis"
391+
}]);
392+
});
393+
394+
test("should be able to follow re-assignment on multiple consecutive traced return values", () => {
395+
const helpers = createTracer(false);
396+
helpers.tracer.trace("os.userInfo", {
397+
followConsecutiveAssignment: true,
398+
followReturnValueAssignement: true,
399+
moduleName: "os"
400+
});
401+
402+
helpers.walkOnCode(`
403+
import os from "os";
404+
405+
const user = [...os.userInfo()];
406+
const userBis = {...user};
407+
const userTer = userBis;
408+
console.log(userTer);
409+
`);
410+
411+
assert.deepEqual(helpers.tracer.getDataFromIdentifier("os.userInfo")?.assignmentMemory, [{
412+
type: "ReturnValueAssignment",
413+
name: "user"
414+
}, {
415+
type: "ReturnValueAssignment",
416+
name: "userBis"
417+
},
418+
{
419+
type: "ReturnValueAssignment",
420+
name: "userTer"
421+
}
422+
]);
423+
});
424+
425+
test("should not be able to follow re-assignment of a traced return value when followConsecutiveAssignment is not on", () => {
426+
const helpers = createTracer(false);
427+
helpers.tracer.trace("os.userInfo", {
428+
followReturnValueAssignement: true,
429+
moduleName: "os"
430+
});
431+
432+
helpers.walkOnCode(`
433+
import os from "os";
434+
435+
const user = [...os.userInfo()];
436+
const userBis = user;
437+
console.log(userBis);
438+
`);
439+
440+
assert.deepEqual(helpers.tracer.getDataFromIdentifier("os.userInfo")?.assignmentMemory, [{
441+
type: "ReturnValueAssignment",
442+
name: "user"
443+
}]);
444+
});

0 commit comments

Comments
 (0)