Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Js to Ts : simulator/src/backupCircuits.ts #417

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 0 additions & 85 deletions src/simulator/src/data/backupCircuit.js

This file was deleted.

125 changes: 125 additions & 0 deletions src/simulator/src/data/backupCircuit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { projectSavedSet } from './project';
import { moduleList, updateOrder } from '../metadata';
import { LayoutData,VerilogMetadata,TestbenchData,Scope,
RestrictedCircuitElements,SaveableObject } from './data.types'

declare const globalScope: Scope;

// Helper function to extract data from an object
function extract(obj: SaveableObject): unknown {
return obj.saveObject();
}

/**
* Check if backup is available
* @param {Scope} scope
* @return {boolean}
* @category data
*/
export function checkIfBackup(scope: Scope): boolean {
for (let i = 0; i < updateOrder.length; i++) {
if ((scope[updateOrder[i]] as unknown[]).length) return true;
}
return false;
}

interface BackupData {
layout: LayoutData;
verilogMetadata: VerilogMetadata;
allNodes: unknown[];
testbenchData: TestbenchData;
id: string;
name: string;
nodes: number[];
restrictedCircuitElementsUsed: RestrictedCircuitElements;
[key: string]: unknown;
}

export function backUp(scope: Scope = globalScope): BackupData {
// Disconnection of subcircuits are needed because these are the connections between nodes
// in current scope and those in the subcircuit's scope
for (let i = 0; i < scope.SubCircuit.length; i++) {
scope.SubCircuit[i].removeConnections();
}

const data: BackupData = {
layout: scope.layout,
verilogMetadata: scope.verilogMetadata,
allNodes: scope.allNodes.map(extract),
testbenchData: scope.testbenchData,
id: scope.id,
name: scope.name,
nodes: [],
restrictedCircuitElementsUsed: scope.restrictedCircuitElementsUsed
};

// Storing details of all module objects
for (let i = 0; i < moduleList.length; i++) {
if ((scope[moduleList[i]] as unknown[]).length) {
data[moduleList[i]] = (scope[moduleList[i]] as SaveableObject[]).map(extract);
}
}

// Storing intermediate nodes (nodes in wires)
data.nodes = scope.nodes.map(node => scope.allNodes.indexOf(node));

// Restoring the connections
for (let i = 0; i < scope.SubCircuit.length; i++) {
scope.SubCircuit[i].makeConnections();
}

return data;
}

export function scheduleBackup(scope: Scope = globalScope): string {
const backup = JSON.stringify(backUp(scope));

// Check if the backup is valid and doesn't contain malicious properties
if (isValidBackup(backup)) {
if (
scope.backups.length === 0 ||
scope.backups[scope.backups.length - 1] !== backup
) {
// Safely assign the backup to scope.backups
scope.backups = [...scope.backups, backup];

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
user controlled input
.

// Safely assign an empty array to scope.history
scope.history = [];

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
user controlled input
.

// Safely assign the current timestamp
scope.timeStamp = new Date().getTime();

Check warning

Code scanning / CodeQL

Prototype-polluting assignment Medium

This assignment may alter Object.prototype if a malicious '__proto__' string is injected from
user controlled input
.

// Mark the project as unsaved
projectSavedSet(false);
}
} else {
console.error("Invalid backup data detected. Backup aborted.");
}

return backup;
}

/**
* Validate the backup data to prevent prototype pollution.
* @param backup The backup data to validate.
* @returns True if the backup is valid, false otherwise.
*/
function isValidBackup(backup: string): boolean {
try {
const parsedBackup = JSON.parse(backup);

// Check if the parsed backup contains any malicious properties
if (parsedBackup && typeof parsedBackup === "object") {
for (const key in parsedBackup) {
if (key === "__proto__" || key === "constructor" || key === "prototype") {
return false; // Malicious property detected
}
}
}

return true; // Backup is valid
} catch (error) {
console.error("Failed to parse backup data:", error);
return false; // Backup is invalid
}
}
55 changes: 55 additions & 0 deletions src/simulator/src/data/data.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export interface LayoutData {
width: number;
height: number;
}

export interface VerilogMetadata {
code: string;
}

export interface TestbenchData {
testCases: TestCase[];
}

interface TestCase {
inputs: Record<string, boolean>;
outputs: Record<string, boolean>;
}

export interface RestrictedCircuitElements {
[elementName: string]: boolean;
}

export interface Scope {
layout: LayoutData;
verilogMetadata: VerilogMetadata;
allNodes: Node[];
testbenchData: TestbenchData;
id: string;
name: string;
SubCircuit: SubCircuit[];
nodes: Node[];
backups: string[];
history: unknown[];
timeStamp: number;
restrictedCircuitElementsUsed: RestrictedCircuitElements;
[key: string]: unknown;
}

interface SubCircuit {
removeConnections(): void;
makeConnections(): void;
saveObject(): SavedSubCircuit;
}

interface SavedSubCircuit {
id: string;
}

export interface SaveableObject {
saveObject(): unknown;
}
interface Node extends SaveableObject {
id: string;
connections: string[];
}
Loading