From eda7314a5d4c1c2f4fbe98b73cf423d762babc45 Mon Sep 17 00:00:00 2001 From: Joe Heffernan Date: Mon, 30 Sep 2024 14:28:02 -0700 Subject: [PATCH] add check and tests for bad offset in getAgentDataFromBuffer --- src/test/util.test.ts | 44 +++++++++++++++++++++++++++++++++++++++++++ src/util.ts | 17 +++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/test/util.test.ts b/src/test/util.test.ts index 47b73f33..f7474906 100644 --- a/src/test/util.test.ts +++ b/src/test/util.test.ts @@ -1,3 +1,4 @@ +import { FrontEndError } from "../simularium"; import { checkAndSanitizePath, compareTimes, @@ -214,6 +215,49 @@ describe("util", () => { subpoints: [63, 64], //"subpoint-1", "subpoint-2" }); }); + test("it throws an error if the data doesn't have the right shape", () => { + // Test with not enough data for the agent object keys + const invalidTestData = [ + 10, + 15, + 20, + 30, + 31, + 32, + 40, + 41, // Missing other values like zrot, cr, nSubPoints, etc. + ]; + const view = new Float32Array(invalidTestData); + + // Expect the function to throw an error when trying to parse this invalid data + expect(() => getAgentDataFromBuffer(view, 0)).toThrow( + FrontEndError + ); + }); + + test("it throws an error if the subpoints exceed available data", () => { + const incompleteSubpointsTestData = [ + 10, //"visType", + 15, //"instanceId", + 20, //"type", + 30, //"x", + 31, //"y", + 32, //"z", + 40, //"xrot", + 41, //"yrot", + 42, //"zrot", + 50, //"cr", + 3, //"nSubPoints" + 60, //"subpoint-1", + 61, // Missing "subpoint-3" + ]; + const view = new Float32Array(incompleteSubpointsTestData); + + // Expect the function to throw an error because there aren't enough subpoints + expect(() => getAgentDataFromBuffer(view, 0)).toThrow( + FrontEndError + ); + }); }); }); }); diff --git a/src/util.ts b/src/util.ts index 3e4d3190..010577c0 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,7 @@ import JsonFileReader from "./simularium/JsonFileReader"; import BinaryFileReader from "./simularium/BinaryFileReader"; import { AGENT_OBJECT_KEYS, AgentData, CachedFrame } from "./simularium/types"; import { BYTES_PER_AGENT, BYTE_SIZE_64_BIT_NUM, nullAgent } from "./constants"; +import { FrontEndError } from "./simularium"; export const compareTimes = ( time1: number, @@ -104,11 +105,27 @@ export const getAgentDataFromBuffer = ( view: Float32Array, offset: number ): AgentData => { + // Check if the buffer has enough data for the AGENT_OBJECT_KEYS + if (offset + AGENT_OBJECT_KEYS.length > view.length) { + throw new FrontEndError( + "Invalid offset: Not enough data in the buffer for agent data." + ); + } const agentData: AgentData = nullAgent(); for (let i = 0; i < AGENT_OBJECT_KEYS.length; i++) { agentData[AGENT_OBJECT_KEYS[i]] = view[offset + i]; } const nSubPoints = agentData["nSubPoints"]; + + // Check if the buffer has enough data for subpoints + const subpointsStart = offset + AGENT_OBJECT_KEYS.length; + const subpointsEnd = subpointsStart + nSubPoints; + + if (subpointsEnd > view.length) { + throw new FrontEndError( + "Invalid offset: Not enough data in the buffer for subpoints." + ); + } agentData.subpoints = Array.from( view.subarray( offset + AGENT_OBJECT_KEYS.length,