mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
Merge pull request #473 from DrDoof/fix/config-replay-skip
config, httpd: skip an over-long line and refuse to store one
This commit is contained in:
4 files changed
+45
-18
No files matched your search
@@ -14,6 +14,12 @@
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
- Config
|
||||||
|
- A startup configuration line longer than the command buffer no longer stops the replay:
|
||||||
|
the offending line is skipped and the following lines are still applied.
|
||||||
|
- The web UI and the configuration upload now refuse a line the replay cannot take,
|
||||||
|
instead of writing it to flash.
|
||||||
|
|
||||||
## Breaking changes
|
## Breaking changes
|
||||||
|
|
||||||
- Config
|
- Config
|
||||||
|
|||||||
+17
-11
@@ -1962,6 +1962,7 @@ void execute_config(void) __banked
|
|||||||
save_cmd = 0;
|
save_cmd = 0;
|
||||||
|
|
||||||
uint8_t cmd_idx = 0;
|
uint8_t cmd_idx = 0;
|
||||||
|
uint8_t skipping = 0;
|
||||||
do {
|
do {
|
||||||
flash_region.addr = pos;
|
flash_region.addr = pos;
|
||||||
flash_region.len = FLASH_READ_BURST_SIZE;
|
flash_region.len = FLASH_READ_BURST_SIZE;
|
||||||
@@ -1972,20 +1973,23 @@ void execute_config(void) __banked
|
|||||||
do {
|
do {
|
||||||
if (cmd_idx >= (CMD_BUF_SIZE - 1)) {
|
if (cmd_idx >= (CMD_BUF_SIZE - 1)) {
|
||||||
cmd_buffer[cmd_idx] = NUL;
|
cmd_buffer[cmd_idx] = NUL;
|
||||||
print_string("ERROR: Command too long: ");
|
print_string("ERROR: Command too long, skipped: ");
|
||||||
print_string_x(cmd_buffer);
|
print_string_x(cmd_buffer);
|
||||||
write_char('\n');
|
write_char('\n');
|
||||||
err_status = ERR_CMD_TOO_LONG;
|
cmd_idx = 0;
|
||||||
goto config_done;
|
skipping = 1;
|
||||||
}
|
}
|
||||||
c = flash_buf[cfg_idx++];
|
c = flash_buf[cfg_idx++];
|
||||||
if (c == 0 || c == '\n') {
|
if (c == 0 || c == '\n') {
|
||||||
cmd_buffer[cmd_idx] = NUL;
|
if (skipping) {
|
||||||
if (cmd_idx) {
|
skipping = 0;
|
||||||
cmd_tokenize();
|
} else {
|
||||||
if (err_status != ERR_OK)
|
cmd_buffer[cmd_idx] = NUL;
|
||||||
goto config_done;
|
if (cmd_idx) {
|
||||||
cmd_parser();
|
cmd_tokenize();
|
||||||
|
if (err_status == ERR_OK)
|
||||||
|
cmd_parser();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
goto config_done;
|
goto config_done;
|
||||||
@@ -1993,8 +1997,10 @@ void execute_config(void) __banked
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_buffer[cmd_idx] = c;
|
if (!skipping) {
|
||||||
cmd_idx++;
|
cmd_buffer[cmd_idx] = c;
|
||||||
|
cmd_idx++;
|
||||||
|
}
|
||||||
} while (cfg_idx);
|
} while (cfg_idx);
|
||||||
|
|
||||||
pages_left--;
|
pages_left--;
|
||||||
|
|||||||
+13
-5
@@ -90,6 +90,7 @@ sy_rebooting:"Rebooting, reconnect in about 20 s",sy_bytes:"bytes",
|
|||||||
cw_title:"Write this startup configuration?",cw_save_title:"Save running configuration to flash?",
|
cw_title:"Write this startup configuration?",cw_save_title:"Save running configuration to flash?",
|
||||||
cw_info:"{n} / 2048 bytes, replayed line by line on every boot",
|
cw_info:"{n} / 2048 bytes, replayed line by line on every boot",
|
||||||
cw_toolarge:"Too large: the config sector accepts at most 2048 bytes. Remove lines first.",
|
cw_toolarge:"Too large: the config sector accepts at most 2048 bytes. Remove lines first.",
|
||||||
|
cw_longline:"Line {n} is {m} bytes long: the switch can only replay lines up to 126 bytes and would skip it on boot, so the write is refused. Shorten it first.",
|
||||||
cw_unknown:"Not in the known config grammar (will still be written): ",cw_empty:"(empty)",
|
cw_unknown:"Not in the known config grammar (will still be written): ",cw_empty:"(empty)",
|
||||||
cw_writing:"Writing configuration...",cw_failed:"config write failed: HTTP {n}",
|
cw_writing:"Writing configuration...",cw_failed:"config write failed: HTTP {n}",
|
||||||
cw_verify_fail:"Verification failed: flash content differs from what was sent. Command log NOT cleared.",
|
cw_verify_fail:"Verification failed: flash content differs from what was sent. Command log NOT cleared.",
|
||||||
@@ -201,6 +202,7 @@ sy_rebooting:"再起動中です。約 20 秒後に再接続してください",
|
|||||||
cw_title:"この起動設定を書き込みますか?",cw_save_title:"実行中の設定をフラッシュに保存しますか?",
|
cw_title:"この起動設定を書き込みますか?",cw_save_title:"実行中の設定をフラッシュに保存しますか?",
|
||||||
cw_info:"{n} / 2048 バイト、起動のたびに 1 行ずつ実行されます",
|
cw_info:"{n} / 2048 バイト、起動のたびに 1 行ずつ実行されます",
|
||||||
cw_toolarge:"サイズ超過: 設定セクタは最大 2048 バイトです。先に行を削除してください。",
|
cw_toolarge:"サイズ超過: 設定セクタは最大 2048 バイトです。先に行を削除してください。",
|
||||||
|
cw_longline:"{n} 行目は {m} バイトです: スイッチが起動時に実行できる行は 126 バイトまでで、この行は読み飛ばされるため、書き込みを拒否します。先に短くしてください。",
|
||||||
cw_unknown:"既知の設定文法に含まれない行 (そのまま書き込まれます): ",cw_empty:"(空)",
|
cw_unknown:"既知の設定文法に含まれない行 (そのまま書き込まれます): ",cw_empty:"(空)",
|
||||||
cw_writing:"設定を書き込み中...",cw_failed:"設定の書き込みに失敗しました: HTTP {n}",
|
cw_writing:"設定を書き込み中...",cw_failed:"設定の書き込みに失敗しました: HTTP {n}",
|
||||||
cw_verify_fail:"検証失敗: フラッシュの内容が送信内容と異なります。コマンドログは消去されていません。",
|
cw_verify_fail:"検証失敗: フラッシュの内容が送信内容と異なります。コマンドログは消去されていません。",
|
||||||
@@ -312,6 +314,7 @@ sy_rebooting:"正在重启,约 20 秒后重新连接",sy_bytes:"字节",
|
|||||||
cw_title:"写入此启动配置?",cw_save_title:"将运行配置保存到 Flash?",
|
cw_title:"写入此启动配置?",cw_save_title:"将运行配置保存到 Flash?",
|
||||||
cw_info:"{n} / 2048 字节,每次启动时逐行执行",
|
cw_info:"{n} / 2048 字节,每次启动时逐行执行",
|
||||||
cw_toolarge:"过大: 配置扇区最多容纳 2048 字节。请先删除部分行。",
|
cw_toolarge:"过大: 配置扇区最多容纳 2048 字节。请先删除部分行。",
|
||||||
|
cw_longline:"第 {n} 行有 {m} 字节: 交换机启动时只能执行不超过 126 字节的行,该行会被跳过,因此拒绝写入。请先缩短该行。",
|
||||||
cw_unknown:"不属于已知配置语法的行 (仍会写入): ",cw_empty:"(空)",
|
cw_unknown:"不属于已知配置语法的行 (仍会写入): ",cw_empty:"(空)",
|
||||||
cw_writing:"正在写入配置...",cw_failed:"配置写入失败: HTTP {n}",
|
cw_writing:"正在写入配置...",cw_failed:"配置写入失败: HTTP {n}",
|
||||||
cw_verify_fail:"校验失败: Flash 内容与发送内容不一致。命令日志未清除。",
|
cw_verify_fail:"校验失败: Flash 内容与发送内容不一致。命令日志未清除。",
|
||||||
@@ -1715,11 +1718,16 @@ function cfgReload(){
|
|||||||
cfgParseKnown(x);
|
cfgParseKnown(x);
|
||||||
}).catch(function(){});
|
}).catch(function(){});
|
||||||
}
|
}
|
||||||
|
function cfgLongLine(v){
|
||||||
|
var ls=v.split("\n");
|
||||||
|
for(var i=0;i<ls.length;i++){var n=new Blob([ls[i]]).size;if(n>126)return{n:i+1,m:n};}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
function cfgBytes(){
|
function cfgBytes(){
|
||||||
var n=new Blob([$("cfgedit").value]).size;
|
var v=$("cfgedit").value,n=new Blob([v]).size;
|
||||||
var el=$("cfgbytes");
|
var el=$("cfgbytes");
|
||||||
el.textContent=n+" / 2048 "+t("sy_bytes");
|
el.textContent=n+" / 2048 "+t("sy_bytes");
|
||||||
el.style.color=n>2048?"var(--bad)":"";
|
el.style.color=(n>2048||cfgLongLine(v))?"var(--bad)":"";
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
$("cfgedit").addEventListener("input",cfgBytes);
|
$("cfgedit").addEventListener("input",cfgBytes);
|
||||||
@@ -1792,12 +1800,12 @@ function writeConfig(txt,title){
|
|||||||
ed.value=txt.replace(/\r\n/g,"\n");
|
ed.value=txt.replace(/\r\n/g,"\n");
|
||||||
var ok=h("button",{class:"ctl pri",text:t("sy_write"),onclick:function(){closeModal();doWriteConfig(cfgText(ed.value))}});
|
var ok=h("button",{class:"ctl pri",text:t("sy_write"),onclick:function(){closeModal();doWriteConfig(cfgText(ed.value))}});
|
||||||
function refresh(){
|
function refresh(){
|
||||||
var v=cfgText(ed.value),bytes=new Blob([v]).size;
|
var v=cfgText(ed.value),bytes=new Blob([v]).size,long=cfgLongLine(v);
|
||||||
var unknown=v.split("\n").filter(function(l){return l.trim()&&!isConfCmd(l.trim().replace(/\s+/g," "))});
|
var unknown=v.split("\n").filter(function(l){return l.trim()&&!isConfCmd(l.trim().replace(/\s+/g," "))});
|
||||||
info.textContent=t("cw_info",{n:bytes});
|
info.textContent=t("cw_info",{n:bytes});
|
||||||
ok.disabled=bytes>2048;
|
ok.disabled=bytes>2048||!!long;
|
||||||
warn.style.color=ok.disabled?"var(--bad)":"var(--warn)";
|
warn.style.color=ok.disabled?"var(--bad)":"var(--warn)";
|
||||||
warn.textContent=ok.disabled?t("cw_toolarge"):(unknown.length?t("cw_unknown")+unknown.join(" | "):"");
|
warn.textContent=bytes>2048?t("cw_toolarge"):long?t("cw_longline",long):(unknown.length?t("cw_unknown")+unknown.join(" | "):"");
|
||||||
}
|
}
|
||||||
ed.addEventListener("input",refresh);refresh();
|
ed.addEventListener("input",refresh);refresh();
|
||||||
modal(title,h("div",null,[info,warn,ed]),[h("button",{class:"ctl",text:t("c_cancel"),onclick:closeModal}),ok]);
|
modal(title,h("div",null,[info,warn,ed]),[h("button",{class:"ctl",text:t("c_cancel"),onclick:closeModal}),ok]);
|
||||||
|
|||||||
+9
-2
@@ -377,8 +377,8 @@ void gen_random_hex_chars(__xdata uint8_t * b, __xdata uint8_t bytes)
|
|||||||
static uint8_t config_take(void)
|
static uint8_t config_take(void)
|
||||||
{
|
{
|
||||||
// #386: needs static, otherwise it still lands in SRAM/DSEG
|
// #386: needs static, otherwise it still lands in SRAM/DSEG
|
||||||
static __xdata uint16_t cfg_pos, cfg_hdr, cfg_body, cfg_end, cfg_last;
|
static __xdata uint16_t cfg_pos, cfg_hdr, cfg_body, cfg_end, cfg_last, cfg_i;
|
||||||
__xdata uint8_t cfg_bl;
|
__xdata uint8_t cfg_bl, cfg_run;
|
||||||
|
|
||||||
cfg_bl = strlen_x(boundary);
|
cfg_bl = strlen_x(boundary);
|
||||||
|
|
||||||
@@ -420,6 +420,13 @@ static uint8_t config_take(void)
|
|||||||
// the payload plus its terminator must fit the sector
|
// the payload plus its terminator must fit the sector
|
||||||
if (cfg_end - cfg_body + 1 > CONFIG_LEN)
|
if (cfg_end - cfg_body + 1 > CONFIG_LEN)
|
||||||
return 2;
|
return 2;
|
||||||
|
cfg_run = 0;
|
||||||
|
for (cfg_i = cfg_body; cfg_i < cfg_end; cfg_i++) {
|
||||||
|
if (config_buf[cfg_i] == '\n')
|
||||||
|
cfg_run = 0;
|
||||||
|
else if (++cfg_run >= CMD_BUF_SIZE - 1)
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
config_buf[cfg_end] = 0;
|
config_buf[cfg_end] = 0;
|
||||||
flash_region.addr = CONFIG_START;
|
flash_region.addr = CONFIG_START;
|
||||||
flash_sector_erase();
|
flash_sector_erase();
|
||||||
|
|||||||
Reference in new issue
Block a user