Fix dangling pointer bug in WiFiManager getSSID/getConnectionName

WiFi.SSID() returns a temporary String object. Calling .c_str() on it
returns a pointer to the internal buffer, but the String is destroyed
at the end of the statement - leaving a dangling pointer.

Fix by caching the SSID in a member variable when connection state
changes, and returning a pointer to that stable storage.

Also fix getWiFiStatus() in MyMesh.cpp which was using WiFiState enum
values instead of NetworkState (the interface return type).
This commit is contained in:
Ryan Malloy 2026-02-05 09:47:01 -07:00
parent 7516c808a7
commit 91d144901a
3 changed files with 15 additions and 11 deletions

View File

@ -1289,9 +1289,9 @@ const char* MyMesh::getMQTTStatus() const {
const char* MyMesh::getWiFiStatus() const { const char* MyMesh::getWiFiStatus() const {
switch (_wifi_mgr.getState()) { switch (_wifi_mgr.getState()) {
case WiFiState::CONNECTED: return "connected"; case NetworkState::CONNECTED: return "connected";
case WiFiState::CONNECTING: return "connecting"; case NetworkState::CONNECTING: return "connecting";
case WiFiState::AP_MODE: return "ap_mode"; case NetworkState::AP_MODE: return "ap_mode";
default: return "disconnected"; default: return "disconnected";
} }
} }

View File

@ -10,6 +10,7 @@ WiFiManager::WiFiManager()
_retry_count(0), _retry_count(0),
_initialized(false) { _initialized(false) {
memset(&_config, 0, sizeof(_config)); memset(&_config, 0, sizeof(_config));
memset(_cached_ssid, 0, sizeof(_cached_ssid));
} }
void WiFiManager::begin(const WiFiConfig& config) { void WiFiManager::begin(const WiFiConfig& config) {
@ -82,6 +83,9 @@ void WiFiManager::loop() {
_state = WiFiState::CONNECTED; _state = WiFiState::CONNECTED;
_connected_since = millis(); _connected_since = millis();
_retry_count = 0; _retry_count = 0;
// Cache SSID to avoid dangling pointer from WiFi.SSID().c_str()
strncpy(_cached_ssid, WiFi.SSID().c_str(), sizeof(_cached_ssid) - 1);
_cached_ssid[sizeof(_cached_ssid) - 1] = '\0';
Serial.printf("[WiFi] Connected! IP: %s, RSSI: %d dBm\n", Serial.printf("[WiFi] Connected! IP: %s, RSSI: %d dBm\n",
WiFi.localIP().toString().c_str(), WiFi.RSSI()); WiFi.localIP().toString().c_str(), WiFi.RSSI());
} else if (status == WL_NO_SSID_AVAIL) { } else if (status == WL_NO_SSID_AVAIL) {
@ -184,6 +188,9 @@ void WiFiManager::startAPMode() {
if (success) { if (success) {
_state = WiFiState::AP_MODE; _state = WiFiState::AP_MODE;
// Cache AP SSID to avoid dangling pointer
strncpy(_cached_ssid, ap_ssid.c_str(), sizeof(_cached_ssid) - 1);
_cached_ssid[sizeof(_cached_ssid) - 1] = '\0';
Serial.printf("[WiFi] AP started: SSID='%s', IP=%s\n", Serial.printf("[WiFi] AP started: SSID='%s', IP=%s\n",
ap_ssid.c_str(), WiFi.softAPIP().toString().c_str()); ap_ssid.c_str(), WiFi.softAPIP().toString().c_str());
} else { } else {
@ -221,10 +228,8 @@ int32_t WiFiManager::getRSSI() const {
} }
const char* WiFiManager::getSSID() const { const char* WiFiManager::getSSID() const {
if (_state == WiFiState::CONNECTED) { if (_state == WiFiState::CONNECTED || _state == WiFiState::AP_MODE) {
return WiFi.SSID().c_str(); return _cached_ssid;
} else if (_state == WiFiState::AP_MODE) {
return WiFi.softAPSSID().c_str();
} }
return ""; return "";
} }
@ -264,10 +269,8 @@ NetworkState WiFiManager::getState() const {
} }
const char* WiFiManager::getConnectionName() const { const char* WiFiManager::getConnectionName() const {
if (_state == WiFiState::CONNECTED) { if (_state == WiFiState::CONNECTED || _state == WiFiState::AP_MODE) {
return WiFi.SSID().c_str(); return _cached_ssid;
} else if (_state == WiFiState::AP_MODE) {
return WiFi.softAPSSID().c_str();
} }
return "Not connected"; return "Not connected";
} }

View File

@ -61,6 +61,7 @@ private:
unsigned long _connected_since; unsigned long _connected_since;
uint8_t _retry_count; uint8_t _retry_count;
bool _initialized; bool _initialized;
char _cached_ssid[33]; // Cached SSID to avoid dangling pointer from WiFi.SSID().c_str()
void attemptConnection(); void attemptConnection();
void checkConnection(); void checkConnection();