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