-
Notifications
You must be signed in to change notification settings - Fork 27
Open
Description
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.
Metadata
Metadata
Assignees
Labels
No labels