qb: Refactor how config.h and config.mk are created.

This is a potential security issue.

The problem is that config.h and config.mk are populated with
all variables prefixed with 'HAVE_' from the user's environment.

Example:

  $ HAVE_FOO=yes ./configure
  $ grep FOO config.mk
  HAVE_FOO = 1
  $ grep FOO config.h
  #define HAVE_FOO 1

After this commit these files will only use variables set by
qb configure process and not from the user's environment. This
issue could result in hard to diagnose undefined behavior or
maybe worse?

The user should experience no change in behavior, but
developers should be more careful about setting 'HAVE_'
variables manually.

Unless the FOO variable is used by check_enabled ($2 only),
check_platform, check_lib, check_pkgconf, check_header,
check_macro or check_switch functions it should be set at
least once by the new add_opt function. The first argument
should be 'FOO' which matches the HAVE_FOO variable and the
second argument should contain 'auto', 'no' or 'yes'.

Example:

  add_opt FOO yes

When in doubt its safe to use add_opt. This will also fix a
few potential issues where configure arguments used by the
user are ignored.

When the second argument is not set the FOO variable will only
be used to populate config.h and config.mk with its current
value. This should only be done in qb/qb.libs.sh in functions
that set 'HAVE_' variables.
This commit is contained in:
orbea 2019-07-27 09:58:17 -07:00
parent 3677170ca3
commit 13cf3cdef2
6 changed files with 67 additions and 30 deletions

View File

@ -1,3 +1,9 @@
# Use add_opt to set HAVE_FOO variables the first time
# example: add_opt FOO no
#
# Only needed when check_enabled ($2), check_platform, check_lib, check_pkgconf,
# check_header, check_macro and check_switch are not used.
check_switch '' C99 -std=gnu99 "Cannot find C99 compatible compiler."
check_switch '' NOUNUSED -Wno-unused-result
add_define MAKEFILE NOUNUSED "$HAVE_NOUNUSED"
@ -59,7 +65,7 @@ if [ "$HAVE_VIDEOCORE" != "no" ]; then
[ -d /opt/vc/lib ] && add_dirs LIBRARY /opt/vc/lib /opt/vc/lib/GL
check_lib '' VIDEOCORE -lbcm_host bcm_host_init "-lvcos -lvchiq_arm"
else
HAVE_VIDEOCORE="$HAVE_VC_TEST"
add_opt VIDEOCORE "$HAVE_VC_TEST"
fi
fi
@ -115,7 +121,7 @@ check_pkgconf EXYNOS libdrm_exynos
if [ "$LIBRETRO" ]; then
die : 'Notice: Explicit libretro used, disabling dynamic libretro loading ...'
HAVE_DYNAMIC='no'
add_opt DYNAMIC no
else
LIBRETRO="-lretro"
fi
@ -144,7 +150,7 @@ fi
check_platform 'Linux Win32' CDROM 'CD-ROM is' user
if [ "$OS" = 'Win32' ]; then
HAVE_DYLIB=yes
add_opt DYLIB yes
else
check_lib '' DYLIB "$DYLIB" dlopen
fi
@ -152,8 +158,8 @@ fi
check_lib '' NETWORKING "$SOCKETLIB" socket "" "$SOCKETHEADER"
if [ "$HAVE_NETWORKING" != 'no' ]; then
HAVE_GETADDRINFO=auto
HAVE_SOCKET_LEGACY=no
add_opt GETADDRINFO auto
add_opt SOCKET_LEGACY no
# WinXP+ implements getaddrinfo()
if [ "$OS" = 'Win32' ]; then
@ -166,9 +172,9 @@ if [ "$HAVE_NETWORKING" != 'no' ]; then
fi
fi
HAVE_NETWORK_CMD=yes
add_opt NETWORK_CMD yes
else
HAVE_NETWORK_CMD=no
add_opt NETWORK_CMD no
fi
check_enabled NETWORKING CHEEVOS cheevos 'Networking is' false
@ -184,9 +190,9 @@ check_lib '' MINIUPNPC '-lminiupnpc'
check_lib '' STDIN_CMD "$CLIB" fcntl
if [ "$HAVE_NETWORK_CMD" = "yes" ] || [ "$HAVE_STDIN_CMD" = "yes" ]; then
HAVE_COMMAND='yes'
add_opt COMMAND yes
else
HAVE_COMMAND='no'
add_opt COMMAND no
fi
check_lib '' GETOPT_LONG "$CLIB" getopt_long
@ -348,7 +354,7 @@ if [ "$HAVE_OPENGL" != 'no' ] && [ "$HAVE_OPENGLES" != 'yes' ]; then
check_pkgconf OSMESA osmesa
fi
else
HAVE_OPENGL='no'
add_opt OPENGL no
fi
check_enabled EGL OPENGLES OpenGLES 'EGL is' false
@ -505,13 +511,13 @@ if [ "$HAVE_MENU" != 'no' ]; then
else
if [ "$HAVE_CACA" != 'yes' ] && [ "$HAVE_SIXEL" != 'yes' ] &&
[ "$HAVE_SDL" != 'yes' ] && [ "$HAVE_SDL2" != 'yes' ]; then
HAVE_RGUI=no
add_opt RGUI no
fi
HAVE_MATERIALUI=no
HAVE_OZONE=no
HAVE_XMB=no
HAVE_STRIPES=no
HAVE_MENU_WIDGETS=no
add_opt MATERIALUI no
add_opt OZONE no
add_opt XMB no
add_opt STRIPES no
add_opt MENU_WIDGETS no
fi
die : 'Notice: Hardware rendering context not available.'
fi

View File

@ -16,7 +16,7 @@ int main(void) { puts("Hai world!"); return 0; }
EOF
cc_works=0
HAVE_CC=no
add_opt CC no
if [ "$CC" ]; then
"$CC" -o "$TEMP_EXE" "$TEMP_C" >/dev/null 2>&1 && cc_works=1
else
@ -53,7 +53,7 @@ int main() { std::cout << "Hai guise" << std::endl; return 0; }
EOF
cxx_works=0
HAVE_CXX=no
add_opt CXX no
if [ "$CXX" ]; then
"$CXX" -o "$TEMP_EXE" "$TEMP_CXX" >/dev/null 2>&1 && cxx_works=1
else

View File

@ -16,7 +16,7 @@ SHARE_DIR="${SHARE_DIR:-${PREFIX}/share}"
# $2 = define
# $3 = value
add_define()
{ eval "${1}_DEFINES=\"\${${1}_DEFINES} $2=$3\""; }
{ eval "${1}_DEFINES=\"\${${1}_DEFINES} $2=$3\""; }
# add_dirs:
# $1 = INCLUDE or LIBRARY
@ -54,7 +54,8 @@ check_compiler()
# $4 = feature
# $5 = enable lib when true, disable errors with 'user' [checked only if non-empty]
check_enabled()
{ setval="$(eval "printf %s \"\$HAVE_$2\"")"
{ add_opt "$2"
setval="$(eval "printf %s \"\$HAVE_$2\"")"
for val in $(printf %s "$1"); do
tmpvar="$(eval "printf %s \"\$HAVE_$val\"")"
@ -89,7 +90,8 @@ check_enabled()
# $3 = feature
# $4 = enable feature when 'true', disable errors with 'user' [checked only if non-empty]
check_platform()
{ tmpval="$(eval "printf %s \"\$HAVE_$2\"")"
{ add_opt "$2"
tmpval="$(eval "printf %s \"\$HAVE_$2\"")"
[ "$tmpval" = 'no' ] && return 0
error=
@ -137,7 +139,8 @@ check_platform()
# $7 = include directory [checked only if non-empty]
# $8 = critical error message [checked only if non-empty]
check_lib()
{ tmpval="$(eval "printf %s \"\$HAVE_$2\"")"
{ add_opt "$2"
tmpval="$(eval "printf %s \"\$HAVE_$2\"")"
[ "$tmpval" = 'no' ] && return 0
check_compiler "$1" "$4"
@ -203,7 +206,8 @@ check_lib()
# $4 = critical error message [checked only if non-empty]
# $5 = force check_lib when true [checked only if non-empty, set by check_val]
check_pkgconf()
{ tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
{ add_opt "$1"
tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
eval "TMP_$1=\$tmpval"
[ "$tmpval" = 'no' ] && return 0
@ -263,7 +267,8 @@ check_pkgconf()
# $1 = HAVE_$1
# $@ = header files
check_header()
{ tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
{ add_opt "$1"
tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
[ "$tmpval" = 'no' ] && return 0
rm -f -- "$TEMP_C"
val="$1"
@ -292,7 +297,8 @@ check_header()
# $2 = macro name
# $3 = header name [included only if non-empty]
check_macro()
{ tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
{ add_opt "$1"
tmpval="$(eval "printf %s \"\$HAVE_$1\"")"
[ "$tmpval" = 'no' ] && return 0
header_include=''
ECHOBUF=''
@ -328,7 +334,8 @@ EOF
# $3 = switch
# $4 = critical error message [checked only if non-empty]
check_switch()
{ check_compiler "$1" ''
{ add_opt "$2"
check_compiler "$1" ''
printf %s\\n 'int main(void) { return 0; }' > "$TEMP_CODE"
answer='no'

View File

@ -1,7 +1,7 @@
# Creates config.mk and config.h.
vars=''
add_define MAKEFILE GLOBAL_CONFIG_DIR "$GLOBAL_CONFIG_DIR"
set -- $(set | grep ^HAVE_)
eval "set -- $CONFIG_OPTS"
while [ $# -gt 0 ]; do
tmpvar="${1%=*}"
shift 1

View File

@ -16,7 +16,7 @@ public:
};
EOF
HAVE_MOC=no
add_opt MOC no
if [ "$HAVE_QT" = "yes" ]; then
moc_works=0
if [ "$MOC" ]; then

View File

@ -1,4 +1,23 @@
print_help_option() # $1 = option $@ = description
# add_opt
# $1 = HAVE_$1
# $2 = value ['auto', 'no' or 'yes', checked only if non-empty]
add_opt()
{ setval="$(eval "printf %s \"\$USER_$1\"")"
[ "${2:-}" ] && ! match "$setval" no yes && eval "HAVE_$1=\"$2\""
for opt in $(printf %s "$CONFIG_OPTS"); do
case "$opt" in
"$1") return 0 ;;
esac
done
CONFIG_OPTS="${CONFIG_OPTS} $1"
}
# print_help_option
# $1 = option
# $@ = description
print_help_option()
{
_opt="$1"
shift 1
@ -68,12 +87,17 @@ opt_exists() # $opt is returned if exists in OPTS
parse_input() # Parse stuff :V
{ BUILD=''
OPTS=''
CONFIG_OPTS=''
config_opts='./configure'
while read -r VAR _; do
TMPVAR="${VAR%=*}"
NEWVAR="${TMPVAR##HAVE_}"
OPTS="$OPTS $NEWVAR"
OPTS="${OPTS} $NEWVAR"
case "$NEWVAR" in
C89_*|CXX_*) : ;;
*) CONFIG_OPTS="${CONFIG_OPTS} $NEWVAR" ;;
esac
eval "USER_$NEWVAR=auto"
done < 'qb/config.params.sh'
#OPTS contains all available options in config.params.sh - used to speedup