Skip to content

Commit

Permalink
wrap fileno() so it works
Browse files Browse the repository at this point in the history
  • Loading branch information
andrew-taylor committed Nov 1, 2023
1 parent 64a7763 commit 7f3798f
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 10 deletions.
5 changes: 3 additions & 2 deletions compile_time_python/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,13 +379,14 @@ def get_rename_arguments(source, options, rename_functions=True):
rename_arguments += ['-Dmain=__fake_variable;extern "C" int __real_main']
else:
rename_arguments += ["-Dmain=__real_main"]
rename_arguments += [f"-D{f}=__wrap_{f}" for f in override_functions]
rename_arguments += [f"-D{f}=__wrap_{f}" for f in ["fileno"] + override_functions]
source = source.replace("__wrap_main", "main")
source = source.replace("__real_fileno", "fileno")
for f in override_functions:
source = source.replace("__real_" + f, f)
else:
rename_arguments += [
"-Wl" + "".join(",-wrap," + f for f in ["main"] + override_functions)
"-Wl" + "".join(",-wrap," + f for f in ["main","fileno"] + override_functions)
]
return rename_arguments, source

Expand Down
9 changes: 9 additions & 0 deletions tests/do_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ export dcc_cpp="${dcc}++"
export c_compiler="${2:-clang}"
export cpp_compiler="${3:-clang++}"

command -v "$dcc" > /dev/null || {
echo "$0: error: $dcc not found"
exit 1
}
command -v "$dcc_cpp" > /dev/null || {
echo "$0: warning: $dcc_cpp not found - no C++ tests will be run"
exit 1
}

e="$tests_dir/extracted_compile_time_errors"
mkdir -p "$e"
(
Expand Down
Empty file.
Empty file.
Empty file.
22 changes: 22 additions & 0 deletions tests/run_time_no_errors/check_exit_status.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

cat >exit_42.c <<eof
#include <stdlib.h>
int main(void) {exit(42);}
eof

cat >return_42.c <<eof
int main(void) {return 42;}
eof

for source in exit_42.c return_42.c
do
$dcc "$source" ||
continue
./a.out
exit_status=$?
test "$exit_status" != 42 &&
echo "$source incorrect exit status: $exit_status" 1>&2
done

rm -f a.out exit_42.c return_42.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//dcc_flags=
//dcc_flags=-fsanitize=address
//dcc_flags=--leak-check

int main(void) {
Expand Down
9 changes: 9 additions & 0 deletions tests/run_time_no_errors/fileno.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <stdio.h>
#include <assert.h>

int main(void) {
assert(fileno(stdin) == 0);
assert(fileno(stdout) == 1);
assert(fileno(stderr) == 2);
assert(fileno(fopen(__FILE__, "r")) == 3);
}
6 changes: 3 additions & 3 deletions tests/single_test.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env bash

command -v "$dcc" > /dev/null || exit 1
command -v "$dcc_cpp" > /dev/null || exit 1

tmpdir=$(mktemp -d)
trap 'cd /;rm -fr "$tmpdir"' EXIT
Expand Down Expand Up @@ -51,7 +50,7 @@ compile_options_list=${compile_options_list:-'dcc_flags=""'}

for compile_options in $compile_options_list
do
rm -f a.out
rm -f a.out tmp.actual_*
compile_options=$(echo "$compile_options"|sed 's/#/ /g')
case "$src_file" in
*.c)
Expand All @@ -65,6 +64,7 @@ do
;;

*.cpp)
command -v "$dcc_cpp" > /dev/null || continue
dcc_flags=
suffix=`echo $compile_options|sed 's/^dcc_flags=//;s/ /_/g;s/["$]//g;s/src_file//;s?/?_?g'`
eval $compile_options
Expand All @@ -76,7 +76,7 @@ do

*.sh)
expected_output_basename="`basename $src_file .sh`"
$src_file </dev/null 2>tmp.actual_stderr >/dev/null
$src_file </dev/null 2>tmp.actual_stderr >tmp.actual_stdout
;;

*)
Expand Down
48 changes: 45 additions & 3 deletions wrapper_c/dcc_dual_sanitizers.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ static FILE *get_cookie(FILE *f, const char *mode) {
}
for (int i = 0; i < FOPEN_MAX; i++) {
if (!file_cookies[i].stream) {
file_cookies[i].fd = fileno(f);
extern int __real_fileno(FILE *stream);
file_cookies[i].fd = __real_fileno(f);
file_cookies[i].stream = f;
file_cookies[i].cookie_stream = open_cookie(&file_cookies[i], mode);
return file_cookies[i].cookie_stream;
Expand All @@ -28,6 +29,7 @@ static FILE *get_cookie(FILE *f, const char *mode) {
return f;
}


static int init_check_output(void);
static void init_cookies(void) {
setbuf(stderr, NULL);
Expand Down Expand Up @@ -135,6 +137,7 @@ enum which_system_call {
sc_clock,
sc_close,
sc_fdopen,
sc_fileno,
sc_fopen,
sc_freopen,
sc_popen,
Expand All @@ -154,6 +157,7 @@ static char *system_call_names[] = {
[sc_close] = "close",
[sc_fopen] = "fopen",
[sc_fdopen] = "fdopen",
[sc_fileno] = "fileno",
[sc_freopen] = "freopen",
[sc_popen] = "popen",
[sc_read] = "read",
Expand Down Expand Up @@ -570,7 +574,6 @@ int __wrap_system(const char *command) {
}



static FILE *fopen_helper(FILE *f, const char *mode, enum which_system_call system_call) {
#if __I_AM_SANITIZER1__
FILE *f1 = get_cookie(f, mode);
Expand Down Expand Up @@ -649,7 +652,8 @@ FILE *__wrap_freopen(const char *pathname, const char *mode, FILE *stream) {
FILE *f1 = __real_freopen(pathname, mode, file_cookies[i].stream);
if (f1) {
file_cookies[i].stream = f1;
file_cookies[i].fd = fileno(f1);
extern int __real_fileno(FILE *stream);
file_cookies[i].fd = __real_fileno(f1);
(void)synchronize_system_call_result(sc_freopen, 1);
return file_cookies[i].cookie_stream;
} else {
Expand Down Expand Up @@ -679,3 +683,41 @@ static void unlink_sanitizer2_executable(void) {
}
}
#endif

static int cookie_stream_to_fd(FILE *stream) {
int fd = -1;
for (int i = 0; i < FOPEN_MAX; i++) {
if (file_cookies[i].cookie_stream == stream) {
fd = file_cookies[i].fd;
break;
}
}

// in single santizer mode cookies are used for stdin, stdout & stderr not files
if (fd == -1) {
extern int __real_fileno(FILE *stream);
fd = __real_fileno(stream);
}
return fd;
}

#if __N_SANITIZERS__ > 1

#undef fileno

int __wrap_fileno(FILE *stream) {
synchronize_system_call(sc_fileno, 0);
#if __I_AM_SANITIZER1__
return synchronize_system_call_result(sc_fileno, cookie_stream_to_fd(stream));
#else
return synchronize_system_call_result(sc_fileno);
#endif
}

#else

int __wrap_fileno(FILE *stream) {
return cookie_stream_to_fd(stream);
}

#endif
2 changes: 1 addition & 1 deletion wrapper_c/dcc_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ int __wrap_main(int argc, char *argv[], char *envp[]) {
clear_stack();
extern char **environ;
int r = __real_main(argc, argv, environ);
debug_printf(2, "__real_main returning %d\n", r);
debug_printf(2, "__real_main exiting %d\n", r);
exit(r);
return 1; // not reached
}
Expand Down
3 changes: 2 additions & 1 deletion wrapper_c/dcc_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ static void launch_valgrind(int argc, char *argv[]) {
sizeof tar_data / sizeof tar_data[0], valgrind_error_pipe);
fflush(valgrind_error_pipe);
setbuf(valgrind_error_pipe, NULL);
valgrind_error_fd = (int)fileno(valgrind_error_pipe);
extern int __real_fileno(FILE *stream);
valgrind_error_fd = (int)__real_fileno(valgrind_error_pipe);
} else {
debug_printf(2, "popen __MONITOR_VALGRIND__ failed");
return;
Expand Down

0 comments on commit 7f3798f

Please sign in to comment.