Skip to content

Commit

Permalink
feat(util): Add intersect for sets and maps
Browse files Browse the repository at this point in the history
  • Loading branch information
jubnzv committed Oct 19, 2024
1 parent 4cdd7ce commit 17ee7dd
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/detectors/builtin/argCopyMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
funName,
} from "../../internals/tact";
import { hasInExpressions } from "../../internals/tact/iterators";
import { intersection } from "../../internals/util";
import { intersectLists } from "../../internals/util";
import { MistiTactWarning, Severity } from "../../internals/warnings";
import { ASTDetector } from "../detector";
import {
Expand Down Expand Up @@ -202,7 +202,7 @@ export class ArgCopyMutation extends ASTDetector {
): Map<string, AstStatement[]> {
const mutations = collectMutations(stmt, { flatStmts: true });
const foundMutations = mutations
? intersection(argNames, mutationNames(mutations.mutatedLocals))
? intersectLists(argNames, mutationNames(mutations.mutatedLocals))
: [];
return foundMutations.reduce((mutationMap, argName) => {
const existingStatements = mutationMap.get(argName) || [];
Expand Down
4 changes: 2 additions & 2 deletions src/detectors/builtin/inheritedStateMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
collectMutations,
mutationNames,
} from "../../internals/tact";
import { intersection } from "../../internals/util";
import { intersectLists } from "../../internals/util";
import { MistiTactWarning, Severity } from "../../internals/warnings";
import { ASTDetector } from "../detector";
import { AstStatement, AstNode } from "@tact-lang/compiler/dist/grammar/ast";
Expand Down Expand Up @@ -99,7 +99,7 @@ export class InheritedStateMutation extends ASTDetector {
): MistiTactWarning[] {
const mutations = collectMutations(stmt);
const foundMutations = mutations
? intersection(
? intersectLists(
inheritedFieldNames,
mutationNames(mutations.mutatedFields),
)
Expand Down
6 changes: 3 additions & 3 deletions src/detectors/builtin/neverAccessedVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
forEachExpression,
} from "../../internals/tact";
import { Transfer } from "../../internals/transfer";
import { mergeSets, isSubsetOf } from "../../internals/util";
import { mergeSets, isSetSubsetOf } from "../../internals/util";
import { unreachable } from "../../internals/util";
import { MistiTactWarning, Severity } from "../../internals/warnings";
import { DataflowDetector, WarningsBehavior } from "../detector";
Expand Down Expand Up @@ -59,8 +59,8 @@ class VariableUsageLattice implements JoinSemilattice<VariableState> {
leq(a: VariableState, b: VariableState): boolean {
return (
[...a.declared.extract()].every((x) => b.declared.has(x)) &&
isSubsetOf(a.accessed, b.accessed) &&
isSubsetOf(a.written, b.written)
isSetSubsetOf(a.accessed, b.accessed) &&
isSetSubsetOf(a.written, b.written)
);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/detectors/builtin/stringReceiversOverlap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { JoinSemilattice } from "../../internals/lattice";
import { WorklistSolver } from "../../internals/solver/";
import { forEachExpression, forEachStatement } from "../../internals/tact";
import { Transfer } from "../../internals/transfer";
import { mergeSets, isSubsetOf } from "../../internals/util";
import { mergeSets, isSetSubsetOf } from "../../internals/util";
import { MistiTactWarning, Severity } from "../../internals/warnings";
import { DataflowDetector } from "../detector";
import {
Expand Down Expand Up @@ -56,8 +56,8 @@ class TaintLattice implements JoinSemilattice<TaintState> {

leq(a: TaintState, b: TaintState): boolean {
return (
isSubsetOf(a.argTaint, b.argTaint) &&
isSubsetOf(a.literalTaint, b.literalTaint)
isSetSubsetOf(a.argTaint, b.argTaint) &&
isSetSubsetOf(a.literalTaint, b.literalTaint)
);
}
}
Expand Down
21 changes: 14 additions & 7 deletions src/internals/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@
import { InternalException } from "./exceptions";
import path from "path";

/**
* Intersection of two lists.
*/
export const intersection = <T>(l1: T[], l2: T[]): T[] =>
l1.filter((element) => l2.includes(element));

export const mergeSets = <T>(lhs: Set<T>, rhs: Set<T>): Set<T> =>
new Set([...lhs, ...rhs]);
export const isSubsetOf = <T>(lhs: Set<T>, rhs: Set<T>): boolean =>
export const isSetSubsetOf = <T>(lhs: Set<T>, rhs: Set<T>): boolean =>
[...lhs].every((elem) => rhs.has(elem));
export const intersectSets = <T>(setA: Set<T>, setB: Set<T>): Set<T> =>
new Set([...setA].filter((item) => setB.has(item)));

export const mergeLists = <T>(lhs: T[], rhs: T[]): T[] => [...lhs, ...rhs];
export const isListSubsetOf = <T>(lhs: T[], rhs: T[]): boolean =>
lhs.every((elem) => rhs.includes(elem));
export const intersectLists = <T>(l1: T[], l2: T[]): T[] =>
l1.filter((element) => l2.includes(element));

export const mergeMaps = <K, V>(lhs: Map<K, V>, rhs: Map<K, V>): Map<K, V> =>
new Map([...lhs, ...rhs]);
export const isMapSubsetOf = <K, V>(lhs: Map<K, V>, rhs: Map<K, V>): boolean =>
[...lhs].every(([key, value]) => rhs.has(key) && rhs.get(key) === value);
export const intersectMaps = <K, V>(
mapA: Map<K, V>,
mapB: Map<K, V>,
): Map<K, V> =>
new Map(
[...mapA].filter(
([key, value]) => mapB.has(key) && mapB.get(key) === value,
),
);

/**
* Unreachable case for exhaustive checking.
Expand Down

0 comments on commit 17ee7dd

Please sign in to comment.