https://sourceware.org/bugzilla/show_bug.cgi?id=34760

            Bug ID: 34760
           Summary: gas: internal error in ginsn_print with
                    --scfi=experimental and a listing for long labels
           Product: binutils
           Version: 2.48 (HEAD)
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: gas
          Assignee: unassigned at sourceware dot org
          Reporter: martin.mirchev at u dot nus.edu
  Target Milestone: ---

With --scfi=experimental and a listing (-a), a user label longer than the
remaining space of the fixed-size ginsn listing buffer makes snprintf()
return more than it wrote, and the final gas_assert in ginsn_print() fails:

$ cat long.s     (label is "very_long_label_" followed by 200 x)
        .text
        .globl f
        .type f, @function
f:
        .cfi_startproc
        push %rbp
        .cfi_def_cfa_offset 16
        jmp very_long_label_xxxx...
very_long_label_xxxx...:
        pop %rbp
        .cfi_def_cfa_offset 8
        ret
        .cfi_endproc
$ as --64 --scfi=experimental -ali=long.lst long.s -o long.o
long.s: Assembler messages:
long.s:5: Warning: SCFI ignores most user-specified CFI directives
long.s:9: Internal error in char *ginsn_print(ginsnS *) at ginsn.c:609.
Please report this bug.

Without -a, or without --scfi, the file assembles fine. The output itself is
already bounded by snprintf; only the bookkeeping of str_size overflows.

Suggested fix: bound the label to the remaining space, so long labels are
truncated in the listing:

--- a/gas/ginsn.c
+++ b/gas/ginsn.c
@@ -565,10 +565,12 @@
     goto end;
   else if (ginsn->type == GINSN_TYPE_SYMBOL)
     {
+      /* User labels can be arbitrarily long: truncate them in the listing. 
*/
       if (GINSN_F_USER_LABEL_P (ginsn))
        str_size += snprintf (ginsn_str + str_size,
                              GINSN_LISTING_LEN - str_size,
-                             " %s", S_GET_NAME (ginsn->sym));
+                             " %.*s", GINSN_LISTING_LEN - str_size - 2,
+                             S_GET_NAME (ginsn->sym));
       else
        str_size += snprintf (ginsn_str + str_size,
                              GINSN_LISTING_LEN - str_size,

With it the example assembles, the listing shows the label truncated, and
for a short label the listing and object are byte-identical to before.
(test input attached)

Seen with binutils 2.47; the same code is present on current master.

This issue was found by an LLM-Enhanced Static Analysis Engine and verified
manually.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to