From 4d47b68600e31801286b87ed48264d04b25b38db Mon Sep 17 00:00:00 2001 From: Quinn Date: Sun, 25 Aug 2024 12:06:52 -0400 Subject: [PATCH] Fixed several buffer overflow issues --- include/BOARD-DEFINITIONS.h | 4 ++ include/Vector3D.h | 52 +++++++++++--------- lib/Board/Board.h | 97 ++++++++++++++++++++++--------------- lib/Board/BoardDriver.h | 3 +- lib/Board/BoardManager.h | 67 ++++++++++++++----------- src/main.cpp | 22 +++++---- 6 files changed, 142 insertions(+), 103 deletions(-) diff --git a/include/BOARD-DEFINITIONS.h b/include/BOARD-DEFINITIONS.h index db1aa63..4dd56da 100644 --- a/include/BOARD-DEFINITIONS.h +++ b/include/BOARD-DEFINITIONS.h @@ -11,6 +11,10 @@ #include "BoardTypes.h" #include "Vector3D.h" +// define some important buffer sizes +static constexpr uint32_t SERIAL_ARG_LENGTH{15}; +static constexpr uint32_t SERIAL_CHAR_LENGTH{SERIAL_ARG_LENGTH*10}; + // define the physical dimensions of the board static constexpr uint32_t BOARD_WIDTH{3}; static constexpr uint32_t BOARD_LENGTH{3}; diff --git a/include/Vector3D.h b/include/Vector3D.h index 6f84399..fdcb83d 100644 --- a/include/Vector3D.h +++ b/include/Vector3D.h @@ -5,6 +5,11 @@ class V3D{ public: + constexpr V3D(const V3D& other): + x(other.x), + y(other.y), + z(other.z){} + constexpr V3D(uint32_t x=0, uint32_t y=0, uint32_t z=0): x(x), y(y), @@ -17,36 +22,35 @@ class V3D{ return *this; } - V3D& operator+(const V3D &other){ - V3D vector{}; - vector.x = this->x + other.x; - vector.y = this->y + other.y; - vector.z = this->z + other.z; - return vector; + V3D& operator+=(const V3D &other){ + this->x += other.x; + this->y += other.y; + this->z += other.z; + return *this; } - V3D& operator-(const V3D &other){ - V3D vector{}; - vector.x = this->x - other.x; - vector.y = this->y - other.y; - vector.z = this->z - other.z; - return vector; + V3D& operator-=(const V3D &other){ + this->x -= other.x; + this->y -= other.y; + this->z -= other.z; + return *this; } - V3D operator/(const uint32_t scalar){ - V3D vector{}; - vector.x = this->x / scalar; - vector.y = this->y / scalar; - vector.z = this->z / scalar; - return vector; + V3D& operator/=(const uint32_t scalar){ + if(scalar == 0){ + return *this; + } + this->x /= scalar; + this->y /= scalar; + this->z /= scalar; + return *this; } - V3D operator*(const uint32_t scalar){ - V3D vector{}; - vector.x = this->x * scalar; - vector.y = this->y * scalar; - vector.z = this->z * scalar; - return vector; + V3D& operator*=(const uint32_t scalar){ + this->x *= scalar; + this->y *= scalar; + this->z *= scalar; + return *this; } bool operator==(const V3D &other){ diff --git a/lib/Board/Board.h b/lib/Board/Board.h index f3b51d8..4133f1d 100644 --- a/lib/Board/Board.h +++ b/lib/Board/Board.h @@ -21,6 +21,7 @@ class Board{ constexpr const V3D &GetSize() const{return BOARD_DIMS;} constexpr uint32_t GetNumberCubes() const{return BOARD_DIMS.x * BOARD_DIMS.y * BOARD_DIMS.z;} + constexpr uint32_t GetMaxDimension(){return std::max(std::max(BOARD_DIMS.x, BOARD_DIMS.y), BOARD_DIMS.z);} /** * @brief Returns a string in the format: * !a,b,c,d,e,f,g,h,i; @@ -29,11 +30,6 @@ class Board{ */ void ToStackString(String& stringBuffer) const; - /** - * @returns Returns an array which contains how many cubes are in each z column on the board - */ - std::array &LinearizeBoard() const; - /** * @brief fill the entire board with the given color * @param color the color to fill the board with @@ -70,14 +66,19 @@ class Board{ void SetStateChanged(bool boardState){this->boardStateHasChanged = boardState;} /** - * @brief Get a column along any axis + * @brief Get a column along any axis read into the sliceBuffer * @param column .z specifies the normal direction of the plane (see PLANE_NORMAL), and * the x,y values specify the location of the column in that plane * to fill. IE To fill one stack at 0,2 I would say give V3D(0,2,PLANE_NORMAL::Z) - * @returns an array of cubes along that column + * @param sliceBuffer an array of pointers to the cubes along that column + * @returns the number of elements written into the slice buffer + * @note That array is stored locally and will be overwritten everytime this function is called. + * Also, any unused spots at the end of the array will be nullptrs + * @warning allocate the size of the slice buffer using GetMaxDimension if you don't know what you're doing! */ - BOARD_TYPES::Cube ** SliceBoard(const V3D &column); + uint32_t SliceBoard(const V3D &column, BOARD_TYPES::Cube ** sliceBuffer); + void PrintEntireBoard() const; private: // this is a 3d array of cubes to represent the board. Good luck visualizing it /* _____________ @@ -97,28 +98,25 @@ class Board{ template void Board::ToStackString(String &stringBuffer) const{ - std::array linearizedBoard = this->LinearizeBoard(); + std::array linearizedBoard; + for(uint32_t x{0}; x < BOARD_DIMS.x; x++){ + for(uint32_t y{0}; y < BOARD_DIMS.y; y++){ + uint32_t boardIndex{x + y*3}; + linearizedBoard[boardIndex] = 0; + for(uint32_t z{0}; z < BOARD_DIMS.z; z++){ + linearizedBoard[boardIndex] += this->cubes[x][y][z].isOccupied; + } + } + } stringBuffer += String(linearizedBoard[0]); for(uint32_t i = 0; i < BOARD_DIMS.x * BOARD_DIMS.y; i++){ stringBuffer += "," + String(linearizedBoard[i]); } -} + // TODO: Delete this before merging into develop + this->PrintEntireBoard(); -template -std::array & Board::LinearizeBoard() const{ - // convert the board into one array where each entry represents the height of one stack - std::array linearizedBoard; - for(uint32_t x{0}; x < BOARD_DIMS.x; x++){ - for(uint32_t y{0}; y < BOARD_DIMS.y; y++){ - for(uint32_t z{0}; z < BOARD_DIMS.z; z++){ - bool isOccupied{this->cubes[x][y][z].isOccupied}; - linearizedBoard[x + y*3] += static_cast(isOccupied); - } - } - } - return linearizedBoard; } template @@ -145,39 +143,58 @@ void Board::SetCubeOccupation(const V3D &position, bool occupation){ } template -BOARD_TYPES::Cube ** Board::SliceBoard(const V3D &column){ +uint32_t Board::SliceBoard(const V3D &column, BOARD_TYPES::Cube ** sliceBuffer){ uint32_t columnLength{0}; - V3D indexIncriment{}; - V3D position{}; + V3D indexIncrimentVector{}; + V3D indexVector{}; + switch(column.z){ case BOARD_TYPES::PLANE_NORMAL::X: columnLength = BOARD_DIMS.x; - indexIncriment.x = 1; - position.z = column.x; - position.y = column.y; + indexIncrimentVector.x = 1; + indexVector.z = column.x; + indexVector.y = column.y; break; case BOARD_TYPES::PLANE_NORMAL::Y: columnLength = BOARD_DIMS.y; - indexIncriment.y = 1; - position.x = column.x; - position.z = column.y; + indexIncrimentVector.y = 1; + indexVector.x = column.x; + indexVector.z = column.y; break; default: case BOARD_TYPES::PLANE_NORMAL::Z: columnLength = BOARD_DIMS.z; - indexIncriment.z = 1; - position.x = column.x; - position.y = column.y; + indexIncrimentVector.z = 1; + indexVector.x = column.x; + indexVector.y = column.y; break; } - BOARD_TYPES::Cube* columnSlice[columnLength]; for(uint32_t i = 0; i < columnLength; i++){ - V3D cubePosition = indexIncriment * i + position; - columnSlice[i] = &(this->cubes[cubePosition.x][cubePosition.y][cubePosition.z]); + if(indexVector.x >= BOARD_DIMS.x || indexVector.y >= BOARD_DIMS.y || indexVector.z >= BOARD_DIMS.z){ + Serial.println("Board::SliceBoard: Index Out of Bounds:" + String(indexVector.x) + "," + String(indexVector.y) + "," + String(indexVector.z)); + return 0; + } + sliceBuffer[i] = &(this->cubes[indexVector.x][indexVector.y][indexVector.z]); + indexVector += indexIncrimentVector; + } + return columnLength; +} + +template +void Board::PrintEntireBoard() const{ + Serial.println("begin"); + + for(uint32_t x = 0; x < BOARD_DIMS.x; x++){ + for(uint32_t y = 0; y < BOARD_DIMS.y; y++){ + for(uint32_t z = 0; z < BOARD_DIMS.z; z++){ + const BOARD_TYPES::Cube &cube = this->cubes[x][y][z]; + Serial.print("Cube X:" + String(x) + ",Y:" + String(y) + ",Z:" + String(z)); + Serial.print("\tColor R:" + String(cube.color.x) + ",G:" + String(cube.color.y) + ",B:" + String(cube.color.z)); + Serial.println("\tOccupied? " + String(cube.isOccupied)); + } + } } - - return columnSlice; } diff --git a/lib/Board/BoardDriver.h b/lib/Board/BoardDriver.h index 6180620..7be2a35 100644 --- a/lib/Board/BoardDriver.h +++ b/lib/Board/BoardDriver.h @@ -90,6 +90,7 @@ template void BoardDriver::Init(){ for(uint32_t i = 0; i < NUM_STACKS; i++){ pinMode(this->stacks[i].ledPin, OUTPUT); + filteredReadings[i] = 0; } // begin doesn't really do anything besides setting the pinmode @@ -159,7 +160,6 @@ uint32_t BoardDriver::GetNumberCubes(uint32_t stackIndex){ (static_cast(this->filteredReadings[stackIndex]) * 0.9) + (static_cast(value) * 0.1) ); - // temporary definitions to define value ranges: uint16_t zeroCubesHigh = 4095; uint16_t zeroCubesLow = 3400; @@ -182,5 +182,6 @@ uint32_t BoardDriver::GetNumberCubes(uint32_t stackIndex){ stackHeight = 3; } + this->filteredReadings[stackIndex] = lowPassADCRead; return stackHeight; } \ No newline at end of file diff --git a/lib/Board/BoardManager.h b/lib/Board/BoardManager.h index 2527057..5dff2c5 100644 --- a/lib/Board/BoardManager.h +++ b/lib/Board/BoardManager.h @@ -39,7 +39,7 @@ class BoardManager{ * @param column the column vector * @param color the color you want the column to be */ - void SetColumnColors(const V3D &column, const V3D *color); + void SetColumnColors(const V3D &column, const V3D *color, uint32_t numColors); /** @@ -64,15 +64,13 @@ class BoardManager{ /** * @brief Get the board occupation state returned in the format a,b,c,d.... */ - String &Board2StackString(); + void Board2StackString(String& messageBuffer); private: BoardDriver &driver; Board board{}; - bool hasBoardChanged{false}; - - void updateBoardColors(const V3D &column); + void updateStackColors(const V3D &column); uint32_t getColumnHeight(BOARD_TYPES::PLANE_NORMAL normal){ switch(normal){ @@ -110,17 +108,30 @@ void BoardManager::Update(){ uint32_t numCubes{this->driver.GetNumberCubes(stackIndex)}; for(uint32_t z = 0; z < BOARD_DIMS.z; z++){ V3D cubePosition{x, y, z}; + // update the cube's occupation this->board.SetCubeOccupation(cubePosition, z < numCubes); - cubePosition.z = BOARD_TYPES::PLANE_NORMAL::Z; - this->driver.UpdateStackLEDs(stackIndex, this->board.SliceBoard(cubePosition), BOARD_DIMS.z); } + + // create the column vector for the slice direction + V3D sliceVector{x,y,BOARD_TYPES::PLANE_NORMAL::Z}; + // create a cube slice array buffer + BOARD_TYPES::Cube* sliceBuffer[BOARD_DIMS.z]; + // have the board slice get read into our buffer + this->board.SliceBoard(sliceVector, sliceBuffer); + // send the board slice to the driver to update its LED colors + this->driver.UpdateStackLEDs(stackIndex, sliceBuffer, BOARD_DIMS.z); } } } template -void BoardManager::updateBoardColors(const V3D &column){ - BOARD_TYPES::Cube ** cubeSlice{this->board.SliceBoard(column)}; +void BoardManager::updateStackColors(const V3D &column){ + // the only column type allowed here is z. + V3D sliceVector{column.x, column.y, BOARD_TYPES::Z}; + // create a buffer for slice board to write the cube slice into + BOARD_TYPES::Cube * cubeSlice[BOARD_DIMS.z]; + this->board.SliceBoard(column, cubeSlice); + uint32_t numCubes{this->getColumnHeight(static_cast(column.z))}; this->driver.UpdateStackLEDs(BOARD_DIMS.x, cubeSlice, numCubes); } @@ -129,45 +140,45 @@ template void BoardManager::SetCubeColor(const V3D &position, const V3D &color){ this->board.SetCubeColor(position, color); V3D slice{position.x, position.y, BOARD_TYPES::PLANE_NORMAL::Z}; - this->updateBoardColors(slice); + this->updateStackColors(slice); } template -void BoardManager::SetColumnColors(const V3D &column, const V3D *color){ +void BoardManager::SetColumnColors(const V3D &column, const V3D *color, uint32_t numColors){ uint32_t columnHeight{this->getColumnHeight(static_cast(column.z))}; - V3D position = column; - for(uint32_t z = 0; z < columnHeight; z++){ - position.z = z; - this->board.SetCubeColor(position, color[z]); + // create a cube pointer buffer and store a board slice into it + BOARD_TYPES::Cube * slicedBoard[columnHeight]; + Serial.println("moments before slicing"); + uint32_t sliceLength{this->board.SliceBoard(column, slicedBoard)}; + Serial.println("setting colors"); + uint32_t maxIndex{std::min(numColors, columnHeight)}; + for(uint32_t i = 0; i < columnHeight; i++){ + slicedBoard[i]->color = color[i]; } - - this->updateBoardColors(column); + Serial.println("End of SetColumnColors"); } template void BoardManager::FillColumnColor(const V3D &column, const V3D &color){ uint32_t columnHeight{this->getColumnHeight(column.z)}; - V3D position = column; - for(uint32_t z = 0; z < columnHeight; z++){ - position.z = z; - this->board.SetCubeColor(position, color); + V3D colors[columnHeight]; + for(uint32_t i = 0; i < columnHeight; i++){ + colors[i] = color; } - this->updateBoardColors(column); + this->SetColumnColors(column, colors); } template -bool BoardManager::HasBoardChanged(){return this->hasBoardChanged;} +bool BoardManager::HasBoardChanged(){return this->board.BoardStateChanged();} template -void BoardManager::ClearBoardChanged(){this->hasBoardChanged = false;} +void BoardManager::ClearBoardChanged(){this->board.SetStateChanged(false);} template -String &BoardManager::Board2StackString(){ - String message{}; - this->board.ToStackString(message); - return message; +void BoardManager::Board2StackString(String& messageBuffer){ + this->board.ToStackString(messageBuffer); } diff --git a/src/main.cpp b/src/main.cpp index 294b4be..924f45f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -27,7 +27,7 @@ TaskHandle_t updateBoardTask; // BluetoothSerial SerialBT; // BluetoothSerialMessage serialMessageBT(&SerialBT); -SerialMessage<500, 10> serialMessage(&Serial); +SerialMessage serialMessage(&Serial); Adafruit_NeoPixel pixelController{BOARD_HEIGHT*2, STACK1_LED_PIN, NEO_GRB + NEO_KHZ800}; @@ -64,7 +64,9 @@ void SetupBluetoothModule(){ void printBoardState(){ GlobalPrint::Print("!0,"); - GlobalPrint::Print(boardManager.Board2StackString()); + String boardString; + boardManager.Board2StackString(boardString); + GlobalPrint::Print(boardString); GlobalPrint::Println(";"); } @@ -80,21 +82,21 @@ void SetStackColor(uint32_t * args, int argsLength){ V3D colors[numColors]; for(int i = 0; i < numColors; i++){ - int red = args[2 + (i * 3)]; - int green = args[3 + (i * 3)]; - int blue = args[4 + (i * 3)]; + uint32_t red = args[2 + (i * 3)]; + uint32_t green = args[3 + (i * 3)]; + uint32_t blue = args[4 + (i * 3)]; colors[i] = V3D{red, green, blue}; } - - boardManager.SetColumnColors(V3D{X_COORD, Y_COORD, BOARD_TYPES::PLANE_NORMAL::Z}, colors); + boardManager.SetColumnColors(V3D{X_COORD, Y_COORD, BOARD_TYPES::PLANE_NORMAL::Z}, colors, numColors); } -void parseData(Message<500, 10> &message){ +void parseData(Message &message){ int32_t * args{message.GetArgs()}; - uint32_t argsLength{message.GetArgsLength()}; + uint32_t argsLength{message.GetPopulatedArgs()}; uint32_t command = args[0]; switch(command){ case Commands::BoardState: + GlobalPrint::Println("Test"); printBoardState(); break; case Commands::PING: @@ -154,7 +156,7 @@ void UpdateBoard(void * params){ boardManager.ClearBoardChanged(); } - boardManager.Update(); + // boardManager.Update(); boardStateTimer += updateTickRate; vTaskDelay(updateTickRate.count());