• xpdev: iniSetString misfiles keys into the wrong section when the targ

    From Rob Swindell@VERT to GitLab note in main/sbbs on Mon Jun 22 18:19:55 2026
    https://gitlab.synchro.net/main/sbbs/-/issues/1168#note_9419

    ## Fixed in `4d5604ba4` (range-29-site)

    Committed to `master` (local; pending push).

    ### What the fix does

    The proposed one-liner was *almost* right but insufficient on its own — applied
    alone it **regressed `iniGetSection()`**: once `section_start()` returns the empty section's body index (the next section's header) instead of the list terminator, `iniGetSection()` — which unconditionally pushed `list[i]` — would
    bleed the following section's header and keys into the result. It only worked before by accident (the old `strListCount` return made `list[i]` NULL).

    So the committed fix is two coordinated parts:

    1. **`find_section()`** now returns the index of the next section header (or the
    list terminator) for an empty section — the correct stop-point for read loops
    *and* the correct insertion point for new keys. The `section_start()` helper
    collapsed to an identity and was removed.
    2. **`iniGetSection()`** now skips its initial push when `list[i]` is a section
    header, so an empty section yields no keys instead of bleeding the next one.

    ### Bonus bug found

    Part 2 also fixes a pre-existing latent bug: `iniGetSection(ROOT)` on a file with
    no root-level keys (one that begins with a `[section]` header) used to return the
    **first named section's** header+keys. That corrupted
    `iniSortSections(list, /*prefix*/ NULL, …)` output — reachable in production from
    `filedat.c`'s `batch_list_sort()` — **duplicating the first entry** of a no-root-keys batch list. Verified on a real file read from disk:

    ```
    iniSortSections(NULL) UNFIXED FIXED
    [first] k1 k2 [first] k1 k2
    [first] k1 k2 <- [second] k1 k2
    [second] k1 k2 (dup gone)
    ```

    Note: no JavaScript `File` ini method reaches this path — `file.iniGetObject()`
    maps to `iniGetNamedStringList()`, which iterates-and-breaks from the section start and was always correct. The bug is only reachable from C callers of `iniGetSection()` / `iniSortSections()`.

    ### Regression test

    Added an in-memory suite under `#ifdef INI_FILE_TEST` (runs when the test binary
    is invoked with no file arguments): 6 checks covering the #1168 misfile, the empty-section read guard, and the empty-root case. It reports **3 failures against the unfixed code and 0 against the fix**, and a fix-1-only build (no `iniGetSection` guard) reports 1 failure — confirming the guard is required, not
    optional.

    — *Authored by Claude (Claude Code), on behalf of @rswindell*

    ---
    ï¿­ Synchronet ï¿­ Vertrauen ï¿­ Home of Synchronet ï¿­ [vert/cvs/bbs].synchro.net
  • From Rob Swindell@VERT to GitLab issue in main/sbbs on Tue Jun 23 15:44:11 2026
    close https://gitlab.synchro.net/main/sbbs/-/issues/1168

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net