• fseditor.js: TypeError crash in unwrap_line() after next line is splic

    From Rob Swindell@1:103/705 to GitLab issue in main/sbbs on Sun Jul 5 23:06:23 2026
    open https://gitlab.synchro.net/main/sbbs/-/issues/1183

    A user editing a message in the full-screen editor crashed with:

    ```
    Fri Jun 26 08:16:59 2026 master/074785210 cvs.synchro.net
    term Node 12 <Cru Jones> !JavaScript /sbbs/exec/fseditor.js line 341: TypeError: line[l + 1] is undefined
    ```

    ## Root cause

    In `unwrap_line()` (`exec/fseditor.js`), the `while` loop guards `line[l+1] != undefined` only at the **top** of each iteration (line 294), but the loop body can remove `line[l+1]` mid-iteration and then dereference it again:

    1. The "unkludge" branch moves word(s) from `line[l+1]` up to `line[l]`; when that empties `line[l+1]`, it is **spliced out** (line 326: `line.splice(l+1,1)`).
    2. Execution then falls through to the *"Get first word(s) of next line"* step, which dereferences `line[l+1].text.match(re)` (line 341) with no re-check. If the spliced line was the last one, `line[l+1]` is now `undefined` → the reported TypeError.

    There's even a TODO comment (lines 321–325, added with the splice) predicting exactly this:

    ```js
    /*
    * TODO: If we splice out the next line,
    * line[l+1] != undefined is not longer
    * guaranteed...
    */
    line.splice(l+1,1);
    ```

    Additionally, the `line[l+1] !== undefined` guard at line 346 is ineffective: lines 344–345 (`line[l].text+=words[1]; line[l].attr+=line[l+1].attr.substr(...)`) dereference `line[l+1]` *before* that check runs, and reaching there with a non-null `words` already implies `line[l+1]` existed at line 341.

    ## Trigger scenario

    Editing near the end of the message where `line[l]` is kludged and the entirety of `line[l+1]` (the final line) fits into the available space — the unkludge pass consumes and splices the last line, then the second match dereferences past the end. User-triggerable in normal editing (word-wrap rejoin after deleting/backspacing).

    ## Suggested fix

    After the unkludge branch (or immediately after the splice), re-check the loop invariant before the second dereference, e.g. insert at line 335:

    ```js
    if(line[l+1] == undefined)
    break;
    ```

    and either delete the now-redundant guard at line 346 or move it above line 344 where it could actually help.

    — *Authored by Claude (Claude Code), on behalf of @rswindell*
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)