Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

delayed unintialised error when writing to files #98

Open
XavierCooney opened this issue Apr 9, 2024 · 0 comments
Open

delayed unintialised error when writing to files #98

XavierCooney opened this issue Apr 9, 2024 · 0 comments

Comments

@XavierCooney
Copy link
Contributor

Errors due to writing unintialised bytes with fputc are reported when the file is flushed, rather than at the fputc call:

$ cat bug.c
#include <stdio.h>

int main(void) {
    char uninitialised;
    FILE *fp = fopen("file", "w");
    fputc(uninitialised, fp);

    fflush(fp);
}
$ dcc -fsanitize=valgrind bug.c -o bug
$ ./bug

Runtime error: uninitialized variable accessed.

Execution stopped in main() in bug.c at line 8:

int main(void) {
    char uninitialised;
    FILE *fp = fopen("file", "w");
    fputc(uninitialised, fp);

--> fflush(fp);
}

Values when execution stopped:

fp = 0x4b88890
uninitialised = <uninitialized value>

If the file doesn't end up getting flushed, students only get an error without information about where it occurred:

$ cat bug.c
#include <stdio.h>

int main(void) {
    char uninitialised;
    FILE *fp = fopen("file", "w");
    fputc(uninitialised, fp);
    // oops forget to fclose(fp);
}
$ dcc -fsanitize=valgrind bug.c -o bug
$ ./bug

Runtime error: uninitialized variable accessed.


$

because the flush is occurring when the file is closed during exit cleanup:

$ DCC_DEBUG=3 ./bug
watch_valgrind() running
valgrind:  ==2589043==
valgrind:  ==2589043== TO DEBUG THIS PROCESS USING GDB: start GDB like this
valgrind:  ==2589043==   /path/to/gdb ./bug
valgrind:  ==2589043== and then give GDB the following command
valgrind:  ==2589043==   target remote | /usr/bin/vgdb --pid=2589043
valgrind:  ==2589043== --pid is optional if only one valgrind process is running
valgrind:  ==2589043==
valgrind:  ==2589043== Syscall param write(buf) points to uninitialised byte(s)
valgrind:  ==2589043==    at 0x4A67240: write (write.c:26)
valgrind:  ==2589043==    by 0x49EFFC4: _IO_file_write@@GLIBC_2.2.5 (fileops.c:1180)
valgrind:  ==2589043==    by 0x49EF37F: new_do_write (fileops.c:448)
valgrind:  ==2589043==    by 0x49F0FD8: _IO_do_write@@GLIBC_2.2.5 (fileops.c:425)
valgrind:  ==2589043==    by 0x49F29A5: _IO_flush_all_lockp (genops.c:706)
valgrind:  ==2589043==    by 0x49F2B59: _IO_cleanup (genops.c:866)
valgrind:  ==2589043==    by 0x49AD511: __run_exit_handlers (exit.c:137)
valgrind:  ==2589043==    by 0x49AD699: exit (exit.c:146)
valgrind:  ==2589043==    by 0x4996250: (below main) (libc_start_call_main.h:74)
valgrind:  ==2589043==  Address 0x4b52c00 is 0 bytes inside a block of size 4,096 alloc'd
valgrind:  ==2589043==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
valgrind:  ==2589043==    by 0x49E48CB: _IO_file_doallocate (filedoalloc.c:101)
valgrind:  ==2589043==    by 0x49F20AF: _IO_doallocbuf (genops.c:347)
valgrind:  ==2589043==    by 0x49F20AF: _IO_doallocbuf (genops.c:342)
valgrind:  ==2589043==    by 0x49F1477: _IO_file_overflow@@GLIBC_2.2.5 (fileops.c:744)
valgrind:  ==2589043==    by 0x137ACB: main (bug.c:6)
valgrind:  ==2589043==
valgrind:  ==2589043== (action on error) vgdb me ...

Runtime error: uninitialized variable accessed.
start_gdb: DCC_PID=2589043 DCC_SANITIZER1_PID= DCC_SANITIZER2_PID= DCC_BINARY=/home/xav/temp/24-04-09/bug
running: ['gdb', '--nx', '--batch', '-ex', "python exec(open('drive_gdb.py', encoding='utf-8', errors='replace').read())", '/home/xav/temp/24-04-09/bug']
attaching gdb to valgrind 2589043
relaying data between gdb and process 2589043
warning: remote target does not support file transfer, attempting to access files from local filesystem.
0x0000000004a67240 in __GI___libc_write (fd=3, buf=0x4b52c00, nbytes=1) at ../sysdeps/unix/sysv/linux/write.c:26
26	../sysdeps/unix/sysv/linux/write.c: No such file or directory.
gdb_attach() returning
explain_error() in drive_gdb.py starting

gdb.execute: where
gdb.execute: -> #0  0x0000000004a67240 in __GI___libc_write (fd=3, buf=0x4b52c00, nbytes=1) at ../sysdeps/unix/sysv/linux/write.c:26
#1  0x00000000049effc5 in _IO_new_file_write (f=0x4b529e0, data=0x4b52c00, n=1) at ./libio/fileops.c:1180
#2  0x00000000049ef380 in new_do_write (fp=0x4b529e0, data=0x4b52c00 '\276' <repeats 200 times>..., to_do=to_do@entry=1) at ./libio/libioP.h:947
#3  0x00000000049f0fd9 in _IO_new_do_write (fp=<optimized out>, data=<optimized out>, to_do=1) at ./libio/fileops.c:425
#4  0x00000000049f29a6 in _IO_flush_all_lockp (do_lock=do_lock@entry=0) at ./libio/libioP.h:947
#5  0x00000000049f2b5a in _IO_cleanup () at ./libio/genops.c:866
#6  0x00000000049ad512 in __run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:137
#7  0x00000000049ad69a in __GI_exit (status=<optimized out>) at ./stdlib/exit.c:146
#8  0x0000000004996251 in __libc_start_call_main (main=main@entry=0x135f70 <__wrap_main>, argc=argc@entry=1, argv=argv@entry=0x1fff000858) at ../sysdeps/nptl/libc_start_call_main.h:74
#9  0x0000000004996305 in __libc_start_main_impl (main=0x135f70 <__wrap_main>, argc=1, argv=0x1fff000858, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x1fff000848) at ../csu/libc-start.c:360
#10 0x000000000010d5a1 in _start ()


Stack:
 #0  0x0000000004a67240 in __GI___libc_write (fd=3, buf=0x4b52c00, nbytes=1) at ../sysdeps/unix/sysv/linux/write.c:26
#1  0x00000000049effc5 in _IO_new_file_write (f=0x4b529e0, data=0x4b52c00, n=1) at ./libio/fileops.c:1180
#2  0x00000000049ef380 in new_do_write (fp=0x4b529e0, data=0x4b52c00 '\276' <repeats 200 times>..., to_do=to_do@entry=1) at ./libio/libioP.h:947
#3  0x00000000049f0fd9 in _IO_new_do_write (fp=<optimized out>, data=<optimized out>, to_do=1) at ./libio/fileops.c:425
#4  0x00000000049f29a6 in _IO_flush_all_lockp (do_lock=do_lock@entry=0) at ./libio/libioP.h:947
#5  0x00000000049f2b5a in _IO_cleanup () at ./libio/genops.c:866
#6  0x00000000049ad512 in __run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:137
#7  0x00000000049ad69a in __GI_exit (status=<optimized out>) at ./stdlib/exit.c:146
#8  0x0000000004996251 in __libc_start_call_main (main=main@entry=0x135f70 <__wrap_main>, argc=argc@entry=1, argv=argv@entry=0x1fff000858) at ../sysdeps/nptl/libc_start_call_main.h:74
#9  0x0000000004996305 in __libc_start_main_impl (main=0x135f70 <__wrap_main>, argc=1, argv=0x1fff000858, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x1fff000848) at ../csu/libc-start.c:360
#10 0x000000000010d5a1 in _start ()


parse_gdb_stack_frame False #0  0x0000000004a67240 in __GI___libc_write (fd=3, buf=0x4b52c00, nbytes=1) at ../sysdeps/unix/sysv/linux/write.c:26
parse_gdb_stack_frame False #1  0x00000000049effc5 in _IO_new_file_write (f=0x4b529e0, data=0x4b52c00, n=1) at ./libio/fileops.c:1180
parse_gdb_stack_frame True #2  0x00000000049ef380 in new_do_write (fp=0x4b529e0, data=0x4b52c00 '\276' <repeats 200 times>..., to_do=to_do@entry=1) at ./libio/libioP.h:947
parse_gdb_stack_frame filename='./libio/libioP.h' m=None
parse_gdb_stack_frame False #3  0x00000000049f0fd9 in _IO_new_do_write (fp=<optimized out>, data=<optimized out>, to_do=1) at ./libio/fileops.c:425
parse_gdb_stack_frame False #4  0x00000000049f29a6 in _IO_flush_all_lockp (do_lock=do_lock@entry=0) at ./libio/libioP.h:947
parse_gdb_stack_frame False #5  0x00000000049f2b5a in _IO_cleanup () at ./libio/genops.c:866
parse_gdb_stack_frame False #6  0x00000000049ad512 in __run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:137
parse_gdb_stack_frame False #7  0x00000000049ad69a in __GI_exit (status=<optimized out>) at ./stdlib/exit.c:146
parse_gdb_stack_frame False #8  0x0000000004996251 in __libc_start_call_main (main=main@entry=0x135f70 <__wrap_main>, argc=argc@entry=1, argv=argv@entry=0x1fff000858) at ../sysdeps/nptl/libc_start_call_main.h:74
parse_gdb_stack_frame False #9  0x0000000004996305 in __libc_start_main_impl (main=0x135f70 <__wrap_main>, argc=1, argv=0x1fff000858, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x1fff000848) at ../csu/libc-start.c:360
parse_gdb_stack_frame False #10 0x000000000010d5a1 in _start ()
parse_gdb_stack_frame False #10 0x000000000010d5a1 in _start ()
parse_gdb_stack_frame False #9  0x0000000004996305 in __libc_start_main_impl (main=0x135f70 <__wrap_main>, argc=1, argv=0x1fff000858, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x1fff000848) at ../csu/libc-start.c:360
parse_gdb_stack_frame False #8  0x0000000004996251 in __libc_start_call_main (main=main@entry=0x135f70 <__wrap_main>, argc=argc@entry=1, argv=argv@entry=0x1fff000858) at ../sysdeps/nptl/libc_start_call_main.h:74
parse_gdb_stack_frame False #7  0x00000000049ad69a in __GI_exit (status=<optimized out>) at ./stdlib/exit.c:146
parse_gdb_stack_frame False #6  0x00000000049ad512 in __run_exit_handlers (status=0, listp=<optimized out>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at ./stdlib/exit.c:137
parse_gdb_stack_frame False #5  0x00000000049f2b5a in _IO_cleanup () at ./libio/genops.c:866
parse_gdb_stack_frame False #4  0x00000000049f29a6 in _IO_flush_all_lockp (do_lock=do_lock@entry=0) at ./libio/libioP.h:947
parse_gdb_stack_frame False #3  0x00000000049f0fd9 in _IO_new_do_write (fp=<optimized out>, data=<optimized out>, to_do=1) at ./libio/fileops.c:425
parse_gdb_stack_frame True #2  0x00000000049ef380 in new_do_write (fp=0x4b529e0, data=0x4b52c00 '\276' <repeats 200 times>..., to_do=to_do@entry=1) at ./libio/libioP.h:947
parse_gdb_stack_frame filename='./libio/libioP.h' m=None
parse_gdb_stack_frame False #1  0x00000000049effc5 in _IO_new_file_write (f=0x4b529e0, data=0x4b52c00, n=1) at ./libio/fileops.c:1180
parse_gdb_stack_frame False #0  0x0000000004a67240 in __GI___libc_write (fd=3, buf=0x4b52c00, nbytes=1) at ../sysdeps/unix/sysv/linux/write.c:26
gdb_set_frame no frame number

gdb.flush
gdb.execute: call (void)__dcc_error_exit()

Program terminated with signal 0, Signal 0.
The program no longer exists.
$ gdb.execute The program being debugged exited while in a function called from GDB.
Evaluation of the expression containing the function
(__dcc_error_exit) will be abandoned.
gdb.execute: ->
gdb.execute: quit
kill_all()

A similar problem arises with other write functions, e.g. fwrite.

As a side note, dcc in dual-sanitizer mode doesn't seem to detect this, although I'm not sure if this is related.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant