diff --git a/src/applications/Tim/Snake.h b/src/applications/Tim/Snake.h index f65ef6a..f576e3e 100644 --- a/src/applications/Tim/Snake.h +++ b/src/applications/Tim/Snake.h @@ -53,14 +53,16 @@ class Snake : public Application } // iterate over the queue and check if the most recent element collides with an older one - for (int i = 0; i < snake_pieces.size() - 1; i++) - { - if (snake_pieces.at(i).x == snake_pieces.back().x && snake_pieces.at(i).y == snake_pieces.back().y) + if (snake_pieces.size() > 1) { + for (int i = 0; i < (int)snake_pieces.size() - 1; i++) { - loose_state = true; - cm->set_controls(button_a); - cm->run_animation(new Splash(snake_pieces.back().x, snake_pieces.back().y, MatrixManager::Color(255, 0, 0)), 1000, 1000); - return; + if (snake_pieces.at(i).x == snake_pieces.back().x && snake_pieces.at(i).y == snake_pieces.back().y) + { + loose_state = true; + cm->set_controls(button_a); + cm->run_animation(new Splash(snake_pieces.back().x, snake_pieces.back().y, MatrixManager::Color(255, 0, 0)), 1000, 1000); + return; + } } } @@ -83,8 +85,8 @@ class Snake : public Application if (food_collision) { - food_position.x = random(0, 11); - food_position.y = random(0, 11); + food_position.x = random(0, 12); + food_position.y = random(0, 12); } } @@ -154,8 +156,8 @@ class Snake : public Application snake_pieces.push_back({3, 5}); food_position = { - random(0, 11), - random(0, 11)}; + random(0, 12), + random(0, 12)}; cm->set_controls(button_up | button_right | button_down | button_left); loose_state = false; direction = -1; diff --git a/src/system/MatrixManager.h b/src/system/MatrixManager.h index b8e65e5..f818c02 100644 --- a/src/system/MatrixManager.h +++ b/src/system/MatrixManager.h @@ -55,6 +55,12 @@ class MatrixManager return; } int pixel = this->calculate_strip_pixel(x, y); + if (pixel < 0 || pixel >= 144) { + if (!ignoreOutOfRange) { + Serial.println(F("Invalid pixel index\n")); + } + return; + } pixels[pixel].R = r; pixels[pixel].G = g; pixels[pixel].B = b; @@ -81,7 +87,7 @@ class MatrixManager */ void set_string(int n, int r, int g, int b) { - if (n > 143) + if (n < 0 || n > 143) { Serial.println(F("Out of range\n")); return; @@ -447,6 +453,10 @@ class MatrixManager */ void circle(int x, int y, int radius, uint32_t color, bool filled = true, int u = 2) { + if (u <= 0) { + Serial.println(F("Invalid step size for circle\n")); + return; + } for (int i = 0; i < 360; i += u) { if (i == 0) diff --git a/src/system/SystemManager.h b/src/system/SystemManager.h index af78474..16f1728 100644 --- a/src/system/SystemManager.h +++ b/src/system/SystemManager.h @@ -154,11 +154,11 @@ class SystemManager { if (current_internal_app->is_wrench) { - if (!transmitting_wrench) + if (!transmitting_wrench && wc != nullptr) { wr_callFunction(wc, "draw"); } - if (wr_getLastError(w) != 0) + if (w != nullptr && wr_getLastError(w) != 0) { Serial.print(F("WREN Error when drawing: ")); Serial.println(wr_getLastError(w)); @@ -196,12 +196,12 @@ class SystemManager game_loop_timer = millis(); if (current_internal_app->is_wrench) { - if (!transmitting_wrench) + if (!transmitting_wrench && wc != nullptr) { wr_callFunction(wc, "game_loop"); } - if (wr_getLastError(w) != 0) + if (w != nullptr && wr_getLastError(w) != 0) { Serial.print(F("WREN Error when game_loop: ")); Serial.println(wr_getLastError(w)); @@ -283,8 +283,9 @@ class SystemManager if (current_internal_app->is_wrench) { Serial.println(F("WRENCH WAS ACTIVE")); - if (!devMode) + if (!devMode && this->wrench_code != nullptr) delete[] this->wrench_code; + this->wrench_code = nullptr; } else { @@ -318,6 +319,11 @@ class SystemManager { Serial.println(F("WRENCH ACTIVE")); w = wr_newState(); // create the state + if (w == nullptr) { + Serial.println(F("Failed to create Wrench state")); + return; + } + wrench_wrapper::register_wrench_functions(w, &ce); wr_loadMathLib(w); wr_loadStringLib(w); @@ -332,11 +338,21 @@ class SystemManager if (!devMode) { + // Clean up existing wrench_code to prevent memory leak + if (this->wrench_code != nullptr) { + delete[] this->wrench_code; + this->wrench_code = nullptr; + } this->wrench_code = new unsigned char[current_internal_app->wrench_code_size]; memcpy_P(this->wrench_code, current_internal_app->wrench_code, current_internal_app->wrench_code_size); } wc = wr_run(w, this->wrench_code, current_internal_app->wrench_code_size); // load and run the code! + if (wc == nullptr) { + Serial.println(F("Failed to run Wrench code")); + return; + } + wr_setAllocatedMemoryGCHint(w, 1000); //print wr_getLastError(w); @@ -811,9 +827,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::UP); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::UP); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -825,9 +843,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::DOWN); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::DOWN); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -839,9 +859,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::LEFT); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::LEFT); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -853,9 +875,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::RIGHT); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::RIGHT); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -867,9 +891,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::MIDDLE); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::MIDDLE); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -881,9 +907,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::A); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::A); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -895,9 +923,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::B); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::B); + wr_callFunction(wc, "on_event", &val, 1); + } } else { @@ -909,9 +939,11 @@ class SystemManager { if (this->current_internal_app->is_wrench) { - WRValue val; - wr_makeInt(&val, Event::C); - wr_callFunction(wc, "on_event", &val, 1); + if (wc != nullptr) { + WRValue val; + wr_makeInt(&val, Event::C); + wr_callFunction(wc, "on_event", &val, 1); + } } else { diff --git a/src/system/WrenchWrapper.h b/src/system/WrenchWrapper.h index 97f11ff..ad05eda 100644 --- a/src/system/WrenchWrapper.h +++ b/src/system/WrenchWrapper.h @@ -108,7 +108,16 @@ namespace wrench_wrapper { if (argn != 3) return; auto ce = static_cast(usr); - ce->mm->set(argv[0].asInt(), argv[1].asInt(), argv[2].asInt()); + if (ce == nullptr || ce->mm == nullptr) return; + + int x = argv[0].asInt(); + int y = argv[1].asInt(); + int color = argv[2].asInt(); + + // Bounds checking to prevent crashes + if (x >= 0 && x <= 11 && y >= 0 && y <= 11) { + ce->mm->set(x, y, color); + } wr_makeInt(&retVal, 1); } @@ -116,7 +125,15 @@ namespace wrench_wrapper { if (argn != 2) return; auto* ce = static_cast(usr); - ce->mm->off(argv[0].asInt(), argv[1].asInt()); + if (ce == nullptr || ce->mm == nullptr) return; + + int x = argv[0].asInt(); + int y = argv[1].asInt(); + + // Bounds checking to prevent crashes + if (x >= 0 && x <= 11 && y >= 0 && y <= 11) { + ce->mm->off(x, y); + } wr_makeInt(&retVal, 1); } @@ -163,7 +180,17 @@ namespace wrench_wrapper { if (argn != 4) return; auto ce = static_cast(usr); - ce->mm->circle(argv[0].asInt(), argv[1].asInt(), argv[2].asInt(), argv[3].asInt()); + if (ce == nullptr || ce->mm == nullptr) return; + + int x = argv[0].asInt(); + int y = argv[1].asInt(); + int radius = argv[2].asInt(); + int color = argv[3].asInt(); + + // Validate radius to prevent issues + if (radius >= 0 && radius < 50) { + ce->mm->circle(x, y, radius, color); + } wr_makeInt(&retVal, 1); }