Menu

#1245 Unbounded `vsprintf` into 1024-byte `runtime_err_str` overflows on long file name in the FILE ASSIGN error path

GC 3.x
accepted
nobody
4
4 days ago
2026-08-20
imiab
No

Unbounded vsprintf into 1024-byte runtime_err_str overflows on long file name in the FILE ASSIGN error path

Summary

A plain COBOL program that OPENs a file with a name longer than ~1010 bytes — no FILE STATUS declared — triggers cob_fatal_errorcob_runtime_error, which formats the file name verbatim into the fixed 1024-byte global runtime_err_str via unbounded vsprintf (libcob/common.c:9058). The overflow happens entirely inside the library's error path; the same call is also reachable via cob_load_collation() (cconv.c:170) and cob_check_numeric().

Version

$ git describe --tags --always
a672a26b

Description

cob_setup_runtime_error_str() formats the message into runtime_err_str[1024] with unbounded vsprintf:

// libcob/common.c:9044-9059
static void COB_NOINLINE
cob_setup_runtime_error_str (const char *fmt, va_list ap)
{
    char *p = runtime_err_str;
    /* ... optional "file:line: " prefix via sprintf, advancing p ... */
    vsprintf (p, fmt, ap);          // line 9058 — should be vsnprintf(p, runtime_err_str + COB_ERRBUF_SIZE - p, fmt, ap)
}

Any error message over ~1010 bytes overflows. No public API is needed: OPEN INPUT F on a missing file with no FILE STATUS clause escalates to cob_fatal_errorcob_runtime_error("%s (status = %02d) for file %s", msg, status, err_cause) with the full caller-supplied file name. A file name in SELECT ... ASSIGN TO is just a program data item, and omitting FILE STATUS is legal COBOL, so the fault is in the library's error path, not the program.

PoC Code

       IDENTIFICATION DIVISION.
       PROGRAM-ID. poc-file.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT F ASSIGN TO WS-FNAME.
       DATA DIVISION.
       FILE SECTION.
       FD F.
       01 R PIC X(10).
       WORKING-STORAGE SECTION.
       01 WS-FNAME PIC X(1500) VALUE ALL 'A'.
       PROCEDURE DIVISION.
           OPEN INPUT F.
           DISPLAY "opened" UPON SYSOUT.
           STOP RUN.

Stack Trace

==309645==ERROR: AddressSanitizer: global-buffer-overflow
WRITE of size 1551 at 0x70f12d08ffc0 thread T0
    #2 cob_setup_runtime_error_str libcob/common.c:9058
    #3 cob_runtime_error           libcob/common.c:9071
    #4 cob_fatal_error            libcob/common.c:9341
    #5 poc__file_                 (poc_min)
0x70f12d08ffc0 is located 0 bytes after global variable 'runtime_err_str' ... of size 1024
SUMMARY: AddressSanitizer: global-buffer-overflow ... in __vsprintf_chk

Reproduction Step

# One-shot Docker reproduction (see gnucobol-issue-attachments.zip):
unzip gnucobol-issue-attachments.zip && cd gnucobol-issue-attachments
./run.sh
# => AddressSanitizer: global-buffer-overflow ... WRITE of size 1551

The same issue is also reproducible on some online COBOL compilers.

Submission Statement

This report was produced by FuzzAnything's AI-assisted library fuzzer and manually verified by a team member.

Signed-off-by: FuzzAnything fuzzanything@gmail.com

1 Attachments

Related

Bugs: #1247

Discussion

  • Arnold Trembley

    Arnold Trembley - 2026-08-20

    Would it be appropriate to truncate the displayed filename to 80 characters (or some similar limit) if the filename is longer than the limit?

    Would that be a difficult or expensive change for the maintainers?

     
    • Simon Sobisch

      Simon Sobisch - 2026-08-20

      We already do that at other places (search the code for" ..." to see how/where that is used), and YES, it is reasonable to memcpy the filename into a local buffer of appropriate size (whatever we use in the other places), if it is too big, replace the last 4 chars (including NUL) by "....", and then sprintf from there, not the original name, before calling into this function in the "for file %s" case.

      Furthermore we should use vsnprintf as noted in the bug report.
      Patches welcome.

       
  • Simon Sobisch

    Simon Sobisch - 4 days ago
    • labels: --> SIGSEGV, libcob, good-first-issue
    • status: open --> accepted
    • Group: unclassified --> GC 3.x
    • Priority: 5 - default --> 4
     
  • Simon Sobisch

    Simon Sobisch - 4 days ago

    We need a general fix for the cob_runtime_error path which fixes the SIGSEGV - outlined in [bugs:#1247] - and a specific "trim down path" + testcase (run_file.at) as outlined here.

    Note that this bug is actually "more relevant" than the other issue, as this can be triggered from a "normal" COBOL program in a relative "normal" path (file just not exists where expected).

     

    Related

    Bugs: #1247


Log in to post a comment.