godbolt.org solves a similar problem by forbidding absolute and relative paths in #include
s:
Input:
#include "/etc/passwd"
Output:
<stdin>:1:1: no absolute or relative includes please
Compilation failed
This can be achieved by running a simple checker on the sources, before invoking the compiler. The checker only has to grep for #include
directives and check the paths against violations of such restrictions. A draft version of such a script (usable with a single source file) follows:
check_includes:
#!/bin/bash
if (( $# != 1 ))
then
echo "Usage: $(basename "$0") source_file"
exit 1
fi
join_lines()
{
sed '/\\$/ {N;s/\\\n//;s/^/\n/;D}' "$1"
}
absolute_includes()
{
join_lines "$1"|grep '^\s*#\s*include\s*["<]\s*/'
}
relative_includes()
{
join_lines "$1"|grep '^\s*#\s*include'|fgrep '../'
}
includes_via_defines()
{
join_lines "$1"|grep '^\s*#\s*include\s*[^"< \t]'
}
show_and_count()
{
tee /dev/stderr|wc -l
}
exit_status=0
if (( 0 != $(absolute_includes "$1"|show_and_count) ))
then
echo 1>&2 "ERROR: $1 contains absolute includes"
exit_status=1
fi
if (( 0 != $(relative_includes "$1"|show_and_count) ))
then
echo 1>&2 "ERROR: $1 contains relative includes"
exit_status=1
fi
if (( 0 != $(includes_via_defines "$1"|show_and_count) ))
then
echo 1>&2 "ERROR: $1 contains includes via defines"
exit_status=1
fi
exit $exit_status
Assuming that the input file can be compiled without errors, this script identifies #include
s that contain absolute or relative paths. It also detects includes done via a macro like below (this can be abused to work around the path checking):
#define HEADER "/etc/password"
#include HEADER