skip_section retains an unrecognized section only up to the first # that appears anywhere in its body:
https://github.com/ctoth/area_reader/blob/3297b88/area_reader/__init__.py#L339-L341
def skip_section(self, section_name):
logger.debug("Skipping section %s", section_name)
self.skipped_sections.append((section_name, self.read_until('#')))
read_until('#') matches a # in ordinary section content (help text, social messages, mobprog code, OLC extension sections), not just the next section header. After the truncated skip, load_sections resumes parsing mid-section, treating whatever follows the embedded # as a section name. README's guarantee — "unrecognized source sections are retained as native sections" — does not hold for any skipped section whose body contains #.
Failure modes (both reproduced)
1. Embedded #$ silently terminates the whole load — data loss with no error.
area_a = ("#AREA\nfile.are~\nName~\nmeta~\n0 0\n\n"
"#SOCIALS\nsmile leans back and thinks of #$ money.\n\n"
"#HELPS\n5 greeting~\nhello~\n0 $~\n\n#$\n")
f = RomAreaFile(path_to(area_a)); f.load_sections()
Output:
(a) helps loaded: 0 (expected 1; 0 means silent data loss)
(a) skipped: [('socials', '\nsmile leans back and thinks of ')]
The #HELPS section after the skipped #SOCIALS is never loaded, the social text is truncated, and no exception is raised.
2. An embedded token matching a known section name is parsed as real data.
area_b = ("#AREA\nfile.are~\nName~\nmeta~\n0 0\n\n"
"#NOTES\nsee the #HELPS section for 42 more~\ninfo~\n0 $~\n\n"
"#$\n")
Output:
(b) ParseError: ...\b.are line 8 col 15 in section helps: Error reading section 'helps'
The #HELPS inside the skipped #NOTES body is treated as a live HELPS section and parsing fails (or, with luckier content, loads garbage helps silently).
A related case that mostly survives by accident: ROM 2.4b6 #MOBPROGS sections contain #vnum record markers, so they get split into a chain of phantom skipped sections whose concatenation happens to reproduce the bytes — until the program text contains $ or a known section word after a #.
Suggested direction
Skipping needs to be section-aware rather than a raw scan to the next #: only treat # as a section boundary when it starts a line (matching how the engines' loaders read section headers), and/or track tilde-string state while scanning. The existing writer-side round-trip tests (test_rom_writer.py etc.) only cover skipped bodies without embedded #, e.g. ("socials", "\nwave wildly~\n"), so a regression test with # inside the body would lock in the fix.
skip_sectionretains an unrecognized section only up to the first#that appears anywhere in its body:https://github.com/ctoth/area_reader/blob/3297b88/area_reader/__init__.py#L339-L341
read_until('#')matches a#in ordinary section content (help text, social messages, mobprog code, OLC extension sections), not just the next section header. After the truncated skip,load_sectionsresumes parsing mid-section, treating whatever follows the embedded#as a section name. README's guarantee — "unrecognized source sections are retained as native sections" — does not hold for any skipped section whose body contains#.Failure modes (both reproduced)
1. Embedded
#$silently terminates the whole load — data loss with no error.Output:
The
#HELPSsection after the skipped#SOCIALSis never loaded, the social text is truncated, and no exception is raised.2. An embedded token matching a known section name is parsed as real data.
Output:
The
#HELPSinside the skipped#NOTESbody is treated as a live HELPS section and parsing fails (or, with luckier content, loads garbage helps silently).A related case that mostly survives by accident: ROM 2.4b6
#MOBPROGSsections contain#vnumrecord markers, so they get split into a chain of phantom skipped sections whose concatenation happens to reproduce the bytes — until the program text contains$or a known section word after a#.Suggested direction
Skipping needs to be section-aware rather than a raw scan to the next
#: only treat#as a section boundary when it starts a line (matching how the engines' loaders read section headers), and/or track tilde-string state while scanning. The existing writer-side round-trip tests (test_rom_writer.pyetc.) only cover skipped bodies without embedded#, e.g.("socials", "\nwave wildly~\n"), so a regression test with#inside the body would lock in the fix.