Skip to content

Commit 7f3798f

Browse files
committed
wrap fileno() so it works
1 parent 64a7763 commit 7f3798f

File tree

14 files changed

+96
-10
lines changed

14 files changed

+96
-10
lines changed

compile_time_python/compile.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,14 @@ def get_rename_arguments(source, options, rename_functions=True):
379379
rename_arguments += ['-Dmain=__fake_variable;extern "C" int __real_main']
380380
else:
381381
rename_arguments += ["-Dmain=__real_main"]
382-
rename_arguments += [f"-D{f}=__wrap_{f}" for f in override_functions]
382+
rename_arguments += [f"-D{f}=__wrap_{f}" for f in ["fileno"] + override_functions]
383383
source = source.replace("__wrap_main", "main")
384+
source = source.replace("__real_fileno", "fileno")
384385
for f in override_functions:
385386
source = source.replace("__real_" + f, f)
386387
else:
387388
rename_arguments += [
388-
"-Wl" + "".join(",-wrap," + f for f in ["main"] + override_functions)
389+
"-Wl" + "".join(",-wrap," + f for f in ["main","fileno"] + override_functions)
389390
]
390391
return rename_arguments, source
391392

tests/do_tests.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ export dcc_cpp="${dcc}++"
1313
export c_compiler="${2:-clang}"
1414
export cpp_compiler="${3:-clang++}"
1515

16+
command -v "$dcc" > /dev/null || {
17+
echo "$0: error: $dcc not found"
18+
exit 1
19+
}
20+
command -v "$dcc_cpp" > /dev/null || {
21+
echo "$0: warning: $dcc_cpp not found - no C++ tests will be run"
22+
exit 1
23+
}
24+
1625
e="$tests_dir/extracted_compile_time_errors"
1726
mkdir -p "$e"
1827
(

tests/expected_output/empty_main--leak-check/000000-clang-14.0-x86_64-pc-linux-gnu.txt

Whitespace-only changes.

tests/expected_output/empty_main-fsanitize=address/000000-clang-14.0-x86_64-pc-linux-gnu.txt

Whitespace-only changes.

tests/expected_output/empty_main/000000-clang-14.0-x86_64-pc-linux-gnu.txt

Whitespace-only changes.

tests/expected_output/fileno/000000-clang-14.0-x86_64-pc-linux-gnu.txt

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
cat >exit_42.c <<eof
4+
#include <stdlib.h>
5+
int main(void) {exit(42);}
6+
eof
7+
8+
cat >return_42.c <<eof
9+
int main(void) {return 42;}
10+
eof
11+
12+
for source in exit_42.c return_42.c
13+
do
14+
$dcc "$source" ||
15+
continue
16+
./a.out
17+
exit_status=$?
18+
test "$exit_status" != 42 &&
19+
echo "$source incorrect exit status: $exit_status" 1>&2
20+
done
21+
22+
rm -f a.out exit_42.c return_42.c

tests/run_time_no_errors/no_leak_empty.c renamed to tests/run_time_no_errors/empty_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//dcc_flags=
2+
//dcc_flags=-fsanitize=address
13
//dcc_flags=--leak-check
24

35
int main(void) {

tests/run_time_no_errors/fileno.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <stdio.h>
2+
#include <assert.h>
3+
4+
int main(void) {
5+
assert(fileno(stdin) == 0);
6+
assert(fileno(stdout) == 1);
7+
assert(fileno(stderr) == 2);
8+
assert(fileno(fopen(__FILE__, "r")) == 3);
9+
}

tests/single_test.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env bash
22

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

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

5251
for compile_options in $compile_options_list
5352
do
54-
rm -f a.out
53+
rm -f a.out tmp.actual_*
5554
compile_options=$(echo "$compile_options"|sed 's/#/ /g')
5655
case "$src_file" in
5756
*.c)
@@ -65,6 +64,7 @@ do
6564
;;
6665

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

7777
*.sh)
7878
expected_output_basename="`basename $src_file .sh`"
79-
$src_file </dev/null 2>tmp.actual_stderr >/dev/null
79+
$src_file </dev/null 2>tmp.actual_stderr >tmp.actual_stdout
8080
;;
8181

8282
*)

wrapper_c/dcc_dual_sanitizers.c

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ static FILE *get_cookie(FILE *f, const char *mode) {
1515
}
1616
for (int i = 0; i < FOPEN_MAX; i++) {
1717
if (!file_cookies[i].stream) {
18-
file_cookies[i].fd = fileno(f);
18+
extern int __real_fileno(FILE *stream);
19+
file_cookies[i].fd = __real_fileno(f);
1920
file_cookies[i].stream = f;
2021
file_cookies[i].cookie_stream = open_cookie(&file_cookies[i], mode);
2122
return file_cookies[i].cookie_stream;
@@ -28,6 +29,7 @@ static FILE *get_cookie(FILE *f, const char *mode) {
2829
return f;
2930
}
3031

32+
3133
static int init_check_output(void);
3234
static void init_cookies(void) {
3335
setbuf(stderr, NULL);
@@ -135,6 +137,7 @@ enum which_system_call {
135137
sc_clock,
136138
sc_close,
137139
sc_fdopen,
140+
sc_fileno,
138141
sc_fopen,
139142
sc_freopen,
140143
sc_popen,
@@ -154,6 +157,7 @@ static char *system_call_names[] = {
154157
[sc_close] = "close",
155158
[sc_fopen] = "fopen",
156159
[sc_fdopen] = "fdopen",
160+
[sc_fileno] = "fileno",
157161
[sc_freopen] = "freopen",
158162
[sc_popen] = "popen",
159163
[sc_read] = "read",
@@ -570,7 +574,6 @@ int __wrap_system(const char *command) {
570574
}
571575

572576

573-
574577
static FILE *fopen_helper(FILE *f, const char *mode, enum which_system_call system_call) {
575578
#if __I_AM_SANITIZER1__
576579
FILE *f1 = get_cookie(f, mode);
@@ -649,7 +652,8 @@ FILE *__wrap_freopen(const char *pathname, const char *mode, FILE *stream) {
649652
FILE *f1 = __real_freopen(pathname, mode, file_cookies[i].stream);
650653
if (f1) {
651654
file_cookies[i].stream = f1;
652-
file_cookies[i].fd = fileno(f1);
655+
extern int __real_fileno(FILE *stream);
656+
file_cookies[i].fd = __real_fileno(f1);
653657
(void)synchronize_system_call_result(sc_freopen, 1);
654658
return file_cookies[i].cookie_stream;
655659
} else {
@@ -679,3 +683,41 @@ static void unlink_sanitizer2_executable(void) {
679683
}
680684
}
681685
#endif
686+
687+
static int cookie_stream_to_fd(FILE *stream) {
688+
int fd = -1;
689+
for (int i = 0; i < FOPEN_MAX; i++) {
690+
if (file_cookies[i].cookie_stream == stream) {
691+
fd = file_cookies[i].fd;
692+
break;
693+
}
694+
}
695+
696+
// in single santizer mode cookies are used for stdin, stdout & stderr not files
697+
if (fd == -1) {
698+
extern int __real_fileno(FILE *stream);
699+
fd = __real_fileno(stream);
700+
}
701+
return fd;
702+
}
703+
704+
#if __N_SANITIZERS__ > 1
705+
706+
#undef fileno
707+
708+
int __wrap_fileno(FILE *stream) {
709+
synchronize_system_call(sc_fileno, 0);
710+
#if __I_AM_SANITIZER1__
711+
return synchronize_system_call_result(sc_fileno, cookie_stream_to_fd(stream));
712+
#else
713+
return synchronize_system_call_result(sc_fileno);
714+
#endif
715+
}
716+
717+
#else
718+
719+
int __wrap_fileno(FILE *stream) {
720+
return cookie_stream_to_fd(stream);
721+
}
722+
723+
#endif

wrapper_c/dcc_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ int __wrap_main(int argc, char *argv[], char *envp[]) {
117117
clear_stack();
118118
extern char **environ;
119119
int r = __real_main(argc, argv, environ);
120-
debug_printf(2, "__real_main returning %d\n", r);
120+
debug_printf(2, "__real_main exiting %d\n", r);
121121
exit(r);
122122
return 1; // not reached
123123
}

wrapper_c/dcc_util.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ static void launch_valgrind(int argc, char *argv[]) {
1313
sizeof tar_data / sizeof tar_data[0], valgrind_error_pipe);
1414
fflush(valgrind_error_pipe);
1515
setbuf(valgrind_error_pipe, NULL);
16-
valgrind_error_fd = (int)fileno(valgrind_error_pipe);
16+
extern int __real_fileno(FILE *stream);
17+
valgrind_error_fd = (int)__real_fileno(valgrind_error_pipe);
1718
} else {
1819
debug_printf(2, "popen __MONITOR_VALGRIND__ failed");
1920
return;

0 commit comments

Comments
 (0)