Skip to content
Open
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- Improved string safety across multiple apps (`eWiFi`, `eBot`, `eRemote`) by ensuring explicit null-termination for all `strncpy` calls.
- Updated `eWiFi` simulation data labels to clearly distinguish mock credentials from production environment configurations.
- Refactored `SCPY` macro in `eRemote` to handle bounds checking and null-termination automatically.

## [2.1.0] - 2026-04-04

### Added
Expand Down
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ if(EAPPS_BUILD_PRODUCTIVITY)
add_subdirectory(apps/ezip)
add_subdirectory(apps/eviewer)
add_subdirectory(apps/esession)
add_subdirectory(apps/etrack)
endif()

if(EAPPS_BUILD_MEDIA)
Expand Down Expand Up @@ -108,6 +107,7 @@ if(EAPPS_BUILD_CONNECTIVITY)
add_subdirectory(apps/echat)
add_subdirectory(apps/eremote)
add_subdirectory(apps/ewifi)
add_subdirectory(apps/etrack)
endif()

if(EAPPS_BUILD_SECURITY)
Expand Down Expand Up @@ -154,7 +154,7 @@ set(CPACK_COMPONENT_SUITE_LAUNCHER_REQUIRED ON)

set(CPACK_COMPONENT_PRODUCTIVITY_DISPLAY_NAME "Productivity Apps (14)")
set(CPACK_COMPONENT_PRODUCTIVITY_DESCRIPTION
"ecal, enote, econverter, ebuffer, efiles, ecleaner, eclock, etools, etimer, epdf, ezip, eviewer, esession, etrack")
"ecal, enote, econverter, ebuffer, efiles, ecleaner, eclock, etools, etimer, epdf, ezip, eviewer, esession")
set(CPACK_COMPONENT_PRODUCTIVITY_GROUP "Individual Apps")

set(CPACK_COMPONENT_MEDIA_DISPLAY_NAME "Media Apps (5)")
Expand All @@ -167,7 +167,7 @@ set(CPACK_COMPONENT_GAMES_DESCRIPTION
set(CPACK_COMPONENT_GAMES_GROUP "Individual Apps")

set(CPACK_COMPONENT_CONNECTIVITY_DISPLAY_NAME "Connectivity Apps (8)")
set(CPACK_COMPONENT_CONNECTIVITY_DESCRIPTION "eftp, eserial, essh, evnc, etunnel, echat, eremote, ewifi")
set(CPACK_COMPONENT_CONNECTIVITY_DESCRIPTION "eftp, eserial, essh, evnc, etunnel, echat, eremote, ewifi, etrack")
set(CPACK_COMPONENT_CONNECTIVITY_GROUP "Individual Apps")

set(CPACK_COMPONENT_SECURITY_DISPLAY_NAME "Security Apps (3)")
Expand Down
18 changes: 14 additions & 4 deletions apps/ebot/ebot.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,14 +247,19 @@ int ebot_fetch_models(ebot_state_t *state) {
char name[64];
if (!json_get_string(p, "name", name, sizeof(name))) break;
strncpy(state->models[state->model_count].name, name, 63);
state->models[state->model_count].name[63] = '\0';

char tier[16];
if (json_get_string(p, "tier", tier, sizeof(tier)))
if (json_get_string(p, "tier", tier, sizeof(tier))) {
strncpy(state->models[state->model_count].tier, tier, 15);
state->models[state->model_count].tier[15] = '\0';
}

char params[16];
if (json_get_string(p, "params", params, sizeof(params)))
if (json_get_string(p, "params", params, sizeof(params))) {
strncpy(state->models[state->model_count].params, params, 15);
state->models[state->model_count].params[15] = '\0';
}

state->model_count++;
p = strstr(p + 1, "\"name\"");
Expand All @@ -280,14 +285,19 @@ int ebot_fetch_tools(ebot_state_t *state) {
char name[64];
if (!json_get_string(p, "name", name, sizeof(name))) break;
strncpy(state->tools[state->tool_count].name, name, 63);
state->tools[state->tool_count].name[63] = '\0';

char desc[256];
if (json_get_string(p, "description", desc, sizeof(desc)))
if (json_get_string(p, "description", desc, sizeof(desc))) {
strncpy(state->tools[state->tool_count].description, desc, 255);
state->tools[state->tool_count].description[255] = '\0';
}

char perm[64];
if (json_get_string(p, "permission", perm, sizeof(perm)))
if (json_get_string(p, "permission", perm, sizeof(perm))) {
strncpy(state->tools[state->tool_count].permission, perm, 63);
state->tools[state->tool_count].permission[63] = '\0';
}

state->tool_count++;
p = strstr(p + 1, "\"name\"");
Expand Down
6 changes: 5 additions & 1 deletion apps/eremote/eremote.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static void load_default_devices(void)
{
memset(s_devices, 0, sizeof(s_devices));

#define SCPY(d,s) strncpy(d,s,sizeof(d)-1)
#define SCPY(d,s) do { strncpy(d,s,sizeof(d)-1); (d)[sizeof(d)-1] = '\0'; } while(0)
SCPY(s_devices[0].name, "Sony TV");
SCPY(s_devices[0].brand, "Sony");
SCPY(s_devices[0].model, "Bravia");
Expand Down Expand Up @@ -305,7 +305,9 @@ static void add_device_cb(lv_event_t *e)
}
memset(&s_devices[s_device_count], 0, sizeof(eremote_device_t));
strncpy(s_devices[s_device_count].name, "New Device", 31);
s_devices[s_device_count].name[31] = '\0';
strncpy(s_devices[s_device_count].brand, "Unknown", 23);
s_devices[s_device_count].brand[23] = '\0';
s_devices[s_device_count].type = EREMOTE_DEV_CUSTOM;
s_devices[s_device_count].conn = EREMOTE_CONN_BLE;
s_devices[s_device_count].op_mode = EREMOTE_MODE_DIRECT;
Expand Down Expand Up @@ -640,6 +642,8 @@ static void rebuild_remote_panel(void)
build_vol_ch(s_remote_panel, btn_bg, btn_fg);
build_media(s_remote_panel, btn_bg, btn_fg);
break;
default:
break;
}

refresh_labels();
Expand Down
5 changes: 5 additions & 0 deletions apps/eremote/eremote_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,20 @@ static int g_scene_count = 0;
void eremote_scenes_init(void)
{
strncpy(g_scenes[0].name, "Movie Mode", 31);
g_scenes[0].name[31] = '\0';
g_scenes[0].steps[0] = (eremote_scene_step_t){0, CMD_POWER, 1, 0};
g_scenes[0].steps[1] = (eremote_scene_step_t){0, CMD_INPUT, 2, 500};
g_scenes[0].steps[2] = (eremote_scene_step_t){1, CMD_POWER, 1, 300};
g_scenes[0].step_count = 3;

strncpy(g_scenes[1].name, "Night Mode", 31);
g_scenes[1].name[31] = '\0';
g_scenes[1].steps[0] = (eremote_scene_step_t){3, CMD_TEMP_DOWN, 20, 0};
g_scenes[1].steps[1] = (eremote_scene_step_t){0, CMD_POWER, 0, 500};
g_scenes[1].step_count = 2;

strncpy(g_scenes[2].name, "Music Mode", 31);
g_scenes[2].name[31] = '\0';
g_scenes[2].steps[0] = (eremote_scene_step_t){1, CMD_POWER, 1, 0};
g_scenes[2].steps[1] = (eremote_scene_step_t){1, CMD_VOL_UP, 60, 300};
g_scenes[2].step_count = 2;
Expand All @@ -308,6 +311,7 @@ static int g_schedule_count = 0;
void eremote_schedules_init(void)
{
strncpy(g_schedules[0].name, "AC Off Timer", 31);
g_schedules[0].name[31] = '\0';
g_schedules[0].hour = 23;
g_schedules[0].minute = 0;
g_schedules[0].days = 0x7F;
Expand All @@ -316,6 +320,7 @@ void eremote_schedules_init(void)
g_schedules[0].enabled = true;

strncpy(g_schedules[1].name, "Morning TV", 31);
g_schedules[1].name[31] = '\0';
g_schedules[1].hour = 7;
g_schedules[1].minute = 30;
g_schedules[1].days = 0x1F;
Expand Down
Loading
Loading