Skip to content

as370: MNOTE severity is swallowed - IHBERMAC macro errors ship as silently deleted statements #39

Description

@mgrossmann

What

as370 treats MNOTE as a printing no-op. In the macro-expansion loop it is skipped alongside the listing controls:

/* as370/src/as370.c:1129 */
if (!strcmp(bo, "PRINT") || !strcmp(bo, "SPACE") || !strcmp(bo, "EJECT") || !strcmp(bo, "MNOTE") || !strcmp(bo, "ACTR")) { pc++; continue; }

The operand — including the severity — is never parsed, so an MNOTE 12,'...' neither prints in any diagnostic stream nor influences the exit code. A real assembler (IFOX00, HLASM) folds the MNOTE severity into the return code; -Werror-style builds rely on that.

Why it matters — this has already shipped broken code twice-detectable, once-shipped

The IBM macro error convention is IHBERMACMNOTE severity 8/12 → MEXIT: the macro deletes the statement and reports the error only through the MNOTE. Under as370 that means a macro-argument error compiles to silence — no instruction, no diagnostic, rc 0.

Shipped instance: libc370 asm/@@aopen.asm:460 wrote FREEMAIN R,LV=(0),A=(1),SP=SUBPOOL; freemain.macro:171 rejects SP= with LV=(0) (IHB019, MNOTE 12) and MEXITs. The storage-shortage cleanup that mvslovers/libc370#83 added therefore never existed, and the buffer leaked exactly when storage was short — found only by scanning the object for the missing SVC 10, fixed in mvslovers/libc370#90 / PR #92 with an on-target red→green probe (tstabuf, JOB00820 → JOB00822).

The same statement shape is one typo away in every FREEMAIN/GETMAIN caller; nothing in the toolchain would notice the next one either.

Ask

  1. Parse the MNOTE operand: MNOTE sev,'text', MNOTE 'text' (severity 0), and the comment form MNOTE *,'text' (stays a no-op).
  2. Print the text to stderr with the severity, like an ordinary diagnostic.
  3. Fold the severity into the assembler return code (rc = max(rc, sev)), so severity >= 8 fails the build under the usual rc checks — mklibc.py already deletes the object and stops on a nonzero rc, so libc370 inherits the protection with no change on its side.

If legacy macros turn out to emit chatty low-severity MNOTEs, a threshold option (e.g. --mnote-level=N, default 8) keeps them printable without failing builds — but the default must not stay "invisible".

Found while fixing mvslovers/libc370#90; the object-scan technique that caught it is not a substitute for the assembler saying so.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions