fix(launcher): app 显示名缓冲 name[17]→[49] + json_str 截断 UTF-8 整序列保护(同 amsd 修复,M6.2 备料 launcher 03dfcf76)
This commit is contained in:
1 parent
8588a6b453
commit
54a6e828b7
3 files changed
+33
-6
No files matched your search
@@ -629,7 +629,7 @@ void ensure_wifi(void)
|
|||||||
void meow_parse_app_json(FILE *f, struct app *a)
|
void meow_parse_app_json(FILE *f, struct app *a)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[256];
|
||||||
char name[17] = "", exec[129] = "", icon[129] = "";
|
char name[49] = "", exec[129] = "", icon[129] = "";
|
||||||
char package[MEOW_APP_ID_MAX] = "";
|
char package[MEOW_APP_ID_MAX] = "";
|
||||||
int fram = 0, immersive = 0;
|
int fram = 0, immersive = 0;
|
||||||
int fullscreen = 0; /* app.json fullscreen=<true|1>(注入 MEOW_FULLSCREEN env,SDK 预先设全屏) */
|
int fullscreen = 0; /* app.json fullscreen=<true|1>(注入 MEOW_FULLSCREEN env,SDK 预先设全屏) */
|
||||||
@@ -1993,7 +1993,14 @@ static int launch_app_chain(struct app *a, const char *chain)
|
|||||||
}
|
}
|
||||||
app_seq_hits++;
|
app_seq_hits++;
|
||||||
app_seq_last = nw;
|
app_seq_last = nw;
|
||||||
if (app_seq_hits >= 3) {
|
/* REPORT §30(真机四连症状④):VOL_DOWN x3 是「应用内强杀」快捷键,但和普通
|
||||||
|
* 调音量(连按音量减几档)冲突——用户连按音量下键会误触发 SIGTERM→SIGKILL,
|
||||||
|
* 前台 App 闪退(ams 日志 `EXIT dev.player.ncm sig=9`)。框架 App(framework=1,
|
||||||
|
* 如 dev.player.ncm)有 SDK 级左缘横扫返回退出(D10 默认,app.c 根页
|
||||||
|
* meow_ui_request_exit),无需此强杀快捷键 → 门控到裸 App(framework=0)才触发,
|
||||||
|
* 框架 App 连按音量键只调音量不再被杀。裸 App 仍保留 VOL_DOWN x3 强杀出口
|
||||||
|
* (无框架返回手势),挂死 App 另可 `meow_ctl am kill <pkg>`。 */
|
||||||
|
if (app_seq_hits >= 3 && !a->framework) {
|
||||||
logmsg("kill seq: VOL_DOWN x3 -> SIGTERM app");
|
logmsg("kill seq: VOL_DOWN x3 -> SIGTERM app");
|
||||||
vol_restore(app_vol0);
|
vol_restore(app_vol0);
|
||||||
kill(pid, SIGTERM);
|
kill(pid, SIGTERM);
|
||||||
@@ -2002,6 +2009,8 @@ static int launch_app_chain(struct app *a, const char *chain)
|
|||||||
reap_wait(pid, &status); /* 有界,防 D-state 挂死 */
|
reap_wait(pid, &status); /* 有界,防 D-state 挂死 */
|
||||||
ams_status_valid = 1;
|
ams_status_valid = 1;
|
||||||
break;
|
break;
|
||||||
|
} else if (app_seq_hits >= 3) {
|
||||||
|
logmsg("VOL_DOWN x3 ignored: framework app (swipe-back exits, §30)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app_prev_vold = vold;
|
app_prev_vold = vold;
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ struct meow_dep {
|
|||||||
struct app {
|
struct app {
|
||||||
char id[MEOW_APP_ID_MAX]; /* M2.52:app_id=app.json 的 package(权威,缺省回退卡上目录名 de->d_name),供 MEOW_LOG_APP 注入 */
|
char id[MEOW_APP_ID_MAX]; /* M2.52:app_id=app.json 的 package(权威,缺省回退卡上目录名 de->d_name),供 MEOW_LOG_APP 注入 */
|
||||||
char package[MEOW_APP_ID_MAX]; /* 安卓化:app.json 的 package 字段(反域名权威标识;目录名=package),scan_apps 据此定 app_id */
|
char package[MEOW_APP_ID_MAX]; /* 安卓化:app.json 的 package 字段(反域名权威标识;目录名=package),scan_apps 据此定 app_id */
|
||||||
char name[17]; /* ASCII display name */
|
char name[49]; /* display name(UTF-8,截断走 json_str 整序列保护) */
|
||||||
char exec[129]; /* absolute path */
|
char exec[129]; /* absolute path */
|
||||||
int ok; /* exec exists and X_OK */
|
int ok; /* exec exists and X_OK */
|
||||||
/* ---- 阶段 D · M1:app.json 路由/框架/服务/图标(scan_apps 解析)---- */
|
/* ---- 阶段 D · M1:app.json 路由/框架/服务/图标(scan_apps 解析)---- */
|
||||||
@@ -333,7 +333,7 @@ struct app {
|
|||||||
* 与 MSG_ACT_DECLARE/HELLO(运行时)并集填充;单一写者=主循环,无需锁。 */
|
* 与 MSG_ACT_DECLARE/HELLO(运行时)并集填充;单一写者=主循环,无需锁。 */
|
||||||
struct meow_acct {
|
struct meow_acct {
|
||||||
char app_id[MEOW_APP_ID_MAX];
|
char app_id[MEOW_APP_ID_MAX];
|
||||||
char name[17];
|
char name[49];
|
||||||
char exec[129];
|
char exec[129];
|
||||||
int ok;
|
int ok;
|
||||||
char framework;
|
char framework;
|
||||||
|
|||||||
@@ -515,9 +515,26 @@ static int ident_ch(char c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 把字符串末尾不完整的 UTF-8 序列砍掉(截断到最后一个完整码点边界)。
|
||||||
|
* 根因记录:显示名按字节截断若落在多字节序列中间,下游(面板 JSON/绘制)
|
||||||
|
* 会拿到非法 UTF-8(amsd「流媒体客户端」事故 2026-09-02)。 */
|
||||||
|
static void utf8_trim_incomplete(char *s)
|
||||||
|
{
|
||||||
|
size_t n = strlen(s), i = 0, last_good = 0;
|
||||||
|
while (i < n) {
|
||||||
|
unsigned char c = (unsigned char)s[i];
|
||||||
|
int len = (c < 0x80) ? 1 : (c >= 0xF0) ? 4 : (c >= 0xE0) ? 3 : (c >= 0xC0) ? 2 : 1;
|
||||||
|
if (i + (size_t)len > n) break;
|
||||||
|
i += (size_t)len;
|
||||||
|
last_good = i;
|
||||||
|
}
|
||||||
|
s[last_good] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 极简 JSON/扁平值提取:在一行里找 key,读取其值(跳过 ':'/'=' 与可选引号)。
|
/* 极简 JSON/扁平值提取:在一行里找 key,读取其值(跳过 ':'/'=' 与可选引号)。
|
||||||
* 支持 JSON `"name": "Hello"` 与扁平 `framework=true`。返回拷贝到 out 的字符数。
|
* 支持 JSON `"name": "Hello"` 与扁平 `framework=true`。返回拷贝到 out 的字符数。
|
||||||
* 返回 0=未命中/空。 */
|
* 返回 0=未命中/空。截断做 UTF-8 整序列保护。 */
|
||||||
int json_str(const char *buf, const char *key, char *out, int olen)
|
int json_str(const char *buf, const char *key, char *out, int olen)
|
||||||
{
|
{
|
||||||
out[0] = 0;
|
out[0] = 0;
|
||||||
@@ -535,7 +552,8 @@ int json_str(const char *buf, const char *key, char *out, int olen)
|
|||||||
out[i++] = *p++;
|
out[i++] = *p++;
|
||||||
out[i] = 0;
|
out[i] = 0;
|
||||||
while (i > 0 && (out[i - 1] == ' ' || out[i - 1] == '\t')) out[--i] = 0;
|
while (i > 0 && (out[i - 1] == ' ' || out[i - 1] == '\t')) out[--i] = 0;
|
||||||
return i;
|
utf8_trim_incomplete(out);
|
||||||
|
return (int)strlen(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user