From 13cf3cdef2cbd02330b6445815a185001c517f38 Mon Sep 17 00:00:00 2001 From: orbea Date: Sat, 27 Jul 2019 09:58:17 -0700 Subject: [PATCH] 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. --- qb/config.libs.sh | 38 ++++++++++++++++++++++---------------- qb/qb.comp.sh | 4 ++-- qb/qb.libs.sh | 23 +++++++++++++++-------- qb/qb.make.sh | 2 +- qb/qb.moc.sh | 2 +- qb/qb.params.sh | 28 ++++++++++++++++++++++++++-- 6 files changed, 67 insertions(+), 30 deletions(-) diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 41c0e7a197..d5e04ce54d 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -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 diff --git a/qb/qb.comp.sh b/qb/qb.comp.sh index 01183b4e3e..053597a0f4 100644 --- a/qb/qb.comp.sh +++ b/qb/qb.comp.sh @@ -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 diff --git a/qb/qb.libs.sh b/qb/qb.libs.sh index 5a256b2857..e912cb8585 100644 --- a/qb/qb.libs.sh +++ b/qb/qb.libs.sh @@ -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' diff --git a/qb/qb.make.sh b/qb/qb.make.sh index 702d5bd8c9..6c255e3ac3 100644 --- a/qb/qb.make.sh +++ b/qb/qb.make.sh @@ -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 diff --git a/qb/qb.moc.sh b/qb/qb.moc.sh index 97bade7a17..cc64c3077b 100644 --- a/qb/qb.moc.sh +++ b/qb/qb.moc.sh @@ -16,7 +16,7 @@ public: }; EOF -HAVE_MOC=no +add_opt MOC no if [ "$HAVE_QT" = "yes" ]; then moc_works=0 if [ "$MOC" ]; then diff --git a/qb/qb.params.sh b/qb/qb.params.sh index 66ec134c12..dfb9922dcd 100644 --- a/qb/qb.params.sh +++ b/qb/qb.params.sh @@ -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