You are not logged in.

#1 2019-11-11 01:29:43

Registered: 2017-11-27
Posts: 38

Compiler bug?


So I have only moderate ability with C, and I'm not en expert on the details of compilers and executables, but I've got a bug in some software I'm writing that I'm wondering might be a compiler bug?

EDIT: I think now that this is a problem in glibc.

The crux of it is this:

(gdb) run -c1
Starting program: /home/ronan/work/misc/dani/dani -c1
FATAL: deadlock in task 1
[Inferior 1 (process 27338) exited with code 01]
(gdb) set disable-randomization off
(gdb) run -c1
Starting program: /home/ronan/work/misc/dani/dani -c1

Program received signal SIGSEGV, Segmentation fault.
0x00007f2e4e83552a in buffered_vfprintf () from /usr/lib/

My program segfaults in fprintf, _only_ with ASLR turned on.

The segfault occurs within a call to fprintf. The source line looks like:

fprintf(stderr, "FATAL: deadlock in task %d\n", current->tid);

which seems fine to me. I get the same ASLR specific segfault even if I replace "current->tid" with a literal "1".

My program is not that complex, ~300 lines C in total, however I cannot reproduce from a toy program like:

#include <stdio.h>

int main(int argc, char *argv[]) {
    fprintf(stderr, "Hello %d\n", 1);
    return 0;

My program is single threaded, but does make use of swapcontext(3). There is no context swap immediately before or after this fprintf, and I don't make explicit use of variadic args / va_args anywhere.

What do you think, could this be a compiler bug? I could post the full source if anyone cares.

The following replacements in the source all work as expected without error:

// Use stdout
fprintf(stdout, "FATAL: deadlock in task %d\n", current->tid);
// Emulate fprintf
char *fmt = "FATAL: deadlock in task %d\n";
int len = snprintf(NULL, 0, fmt, current->tid) + 1;
char *msg = malloc(len * sizeof (char));
snprintf(msg, len, fmt, current->tid);
fputs(msg, stderr);
// Format string
fprintf(stderr, "%s", "wtf\n");

And to be clear, I use 'fprintf(stderr, ...' elsewhere in this project, and I've tested that those work fine. It's only this specific fprintf.

The following similar replacements do NOT work. They present the same segfault:

// Format string, moved newline
fprintf(stderr, "%s\n", "wtf");
// Original with newline removed
fprintf(stderr, "FATAL: deadlock in task %d", current->tid);
// Original with newline in format item
fprintf(stderr, "FATAL: deadlock in task %d%s", current->tid, "\n");

A friend tested it on their ubuntu vm and got the same results.

reproduced with backtrace on glibc-git{,-debug) from [eschwartz] repo:

#0  0x00007f18e76585aa in buffered_vfprintf (s=s@entry=0x7f18e77ab420 <_IO_2_1_stderr_>, 
    format=format@entry=0x556230ce103f "FATAL: deadlock in task %d\n", args=args@entry=0x5562311ac5b0, 
    mode_flags=mode_flags@entry=0) at vfprintf-internal.c:2357
        buf = "\000\000\000\000\000\000\000\000\221\002", '\000' <repeats 654 times>...
        helper = <error reading variable helper (Cannot access memory at address 0x5562311a9f00)>
        hp = 0x5562311a9f00
        result = <optimized out>
        to_flush = <optimized out>
#1  0x00007f18e7655794 in __vfprintf_internal (s=0x7f18e77ab420 <_IO_2_1_stderr_>, 
    format=0x556230ce103f "FATAL: deadlock in task %d\n", ap=ap@entry=0x5562311ac5b0, 
    mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1346
        thousands_sep = 0x0
        grouping = <optimized out>
        done = <optimized out>
        f = 0x5562311ac1c0 "\377\377\377\377"
        lead_str_end = <optimized out>
        end_of_spec = <optimized out>
        work_buffer = "\000\000\000\000\000\000\000\000p\025{\347\030\177\000\000 \241\201\347\030\177\000\000\200\244\201\347\030\177", '\000' <repeats 18 times>, "\001", '\000' <repeats 15 times>, "\377\377\377\377", '\000' <repeats 12 times>, "\340\321_\347\030\177\000\000\000\020{\347\030\177", '\000' <repeats 58 times>, "P0\316\060bU\000\000\260\306\032\061bU\000\000 \361\315\060bU\000\000\320 a%\376\177", '\000' <repeats 18 times>...
        workstart = 0x0
        workend = <optimized out>
        ap_save = {{gp_offset = 3883603312, fp_offset = 32536, overflow_arg_area = 0x1, 
            reg_save_area = 0x0}}
        nspecs_done = <optimized out>
        save_errno = 0
        readonly_format = 0
        __PRETTY_FUNCTION__ = "__vfprintf_internal"
        __result = <optimized out>
#2  0x00007f18e764218a in __fprintf (stream=<optimized out>, format=<optimized out>) at fprintf.c:32
        arg = {{gp_offset = 16, fp_offset = 48, overflow_arg_area = 0x5562311ac690, 
            reg_save_area = 0x5562311ac5d0}}
        done = <optimized out>
#3  0x0000556230cdf443 in wait (sem=0x5562311ac750) at semaphore.c:37
        current = 0x5562311aa300
#4  0x0000556230cdfe4d in consumer () at main.c:45
        producer = 0
        value = 0
        item = {0, 0}
        count = 1
        id = 1
#5  0x00007f18e763c330 in ?? () at ../sysdeps/unix/sysv/linux/x86_64/__start_context.S:91
   from /usr/lib/
No locals.
#6  0x00007ffe25611c00 in ?? ()
No symbol table info available.
#7  0x0000000000000000 in ?? ()
No symbol table info available.

Last edited by Brocellous (2019-11-12 23:32:10)


#2 2020-01-30 09:17:41

Registered: 2018-02-27
Posts: 12

Re: Compiler bug?

Have you tried to run gcc sanitizer first?


#3 2020-02-17 01:12:29

Registered: 2017-11-27
Posts: 38

Re: Compiler bug?

johannkokos wrote:

Have you tried to run gcc sanitizer first?

Thanks for the suggestion, but -fsanatize=address gives a big warning:

WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!

In any case, if I run it, it just reiterates the segfault. So I'm not sure I can make use of asan here.

After some investigation, I've given up on understanding what's happening here for now. It's a very short code path that produces the error, and it contains only 1 swapcontext call. If I reconsider this problem again in the future I'll be sure to provide a minimal example.


Board footer

Powered by FluxBB