2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-22 18:08:23 +00:00

Add check for C99 compliant (v)snprintf function.

This commit is contained in:
Todd C. Miller 2013-11-19 10:40:25 -07:00
parent 0a47860ef7
commit 42b1e4a9c4
7 changed files with 233 additions and 29 deletions

View File

@ -157,6 +157,7 @@ install-sh
ltmain.sh ltmain.sh
m4/ax_check_compile_flag.m4 m4/ax_check_compile_flag.m4
m4/ax_check_link_flag.m4 m4/ax_check_link_flag.m4
m4/ax_func_snprintf.m4
m4/libtool.m4 m4/libtool.m4
m4/ltoptions.m4 m4/ltoptions.m4
m4/ltsugar.m4 m4/ltsugar.m4

1
aclocal.m4 vendored
View File

@ -128,6 +128,7 @@ AC_DEFUN([_AC_TYPE_LONG_LONG_SNIPPET],
m4_include([m4/ax_check_compile_flag.m4]) m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_check_link_flag.m4]) m4_include([m4/ax_check_link_flag.m4])
m4_include([m4/ax_func_snprintf.m4])
m4_include([m4/libtool.m4]) m4_include([m4/libtool.m4])
m4_include([m4/ltoptions.m4]) m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4]) m4_include([m4/ltsugar.m4])

View File

@ -41,7 +41,9 @@
#include <config.h> #include <config.h>
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF) || !defined(HAVE_VASPRINTF) || !defined(HAVE_ASPRINTF) #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_SNPRINTF) || \
!defined(HAVE_VASPRINTF) || !defined(HAVE_ASPRINTF) || \
defined(PREFER_PORTABLE_SNPRINTF)
#include <sys/types.h> #include <sys/types.h>
@ -668,16 +670,16 @@ done:
/* NOTREACHED */ /* NOTREACHED */
} }
#ifndef HAVE_VSNPRINTF #if !defined(HAVE_VSNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
int int
vsnprintf(char *str, size_t n, const char *fmt, va_list ap) vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
{ {
return xxxprintf(&str, n, 0, fmt, ap); return xxxprintf(&str, n, 0, fmt, ap);
} }
#endif /* HAVE_VSNPRINTF */ #endif /* !HAVE_VSNPRINTF || PREFER_PORTABLE_SNPRINTF */
#ifndef HAVE_SNPRINTF #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
int int
snprintf(char *str, size_t n, char const *fmt, ...) snprintf(char *str, size_t n, char const *fmt, ...)
{ {
@ -689,18 +691,18 @@ snprintf(char *str, size_t n, char const *fmt, ...)
va_end(ap); va_end(ap);
return ret; return ret;
} }
#endif /* HAVE_SNPRINTF */ #endif /* !HAVE_SNPRINTF || PREFER_PORTABLE_SNPRINTF */
#ifndef HAVE_VASPRINTF #if !defined(HAVE_VASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
int int
vasprintf(char **str, const char *fmt, va_list ap) vasprintf(char **str, const char *fmt, va_list ap)
{ {
return xxxprintf(str, 0, 1, fmt, ap); return xxxprintf(str, 0, 1, fmt, ap);
} }
#endif /* HAVE_VASPRINTF */ #endif /* !HAVE_VASPRINTF || PREFER_PORTABLE_SNPRINTF */
#ifndef HAVE_ASPRINTF #if !defined(HAVE_ASPRINTF) || defined(PREFER_PORTABLE_SNPRINTF)
int int
asprintf(char **str, char const *fmt, ...) asprintf(char **str, char const *fmt, ...)
{ {
@ -712,6 +714,6 @@ asprintf(char **str, char const *fmt, ...)
va_end(ap); va_end(ap);
return ret; return ret;
} }
#endif /* HAVE_ASPRINTF */ #endif /* !HAVE_ASPRINTF || PREFER_PORTABLE_SNPRINTF */
#endif /* !HAVE_VSNPRINTF || !HAVE_SNPRINTF || !HAVE_VASPRINTF || !HAVE_ASPRINTF */ #endif /* !HAVE_VSNPRINTF || !HAVE_SNPRINTF || !HAVE_VASPRINTF || !HAVE_ASPRINTF || PREFER_PORTABLE_SNPRINTF */

View File

@ -937,6 +937,9 @@
ones. */ ones. */
#undef PC_INSULTS #undef PC_INSULTS
/* Enable replacement (v)snprintf if system (v)snprintf is broken. */
#undef PREFER_PORTABLE_SNPRINTF
/* The syslog priority sudo will use for unsuccessful attempts/errors. */ /* The syslog priority sudo will use for unsuccessful attempts/errors. */
#undef PRI_FAILURE #undef PRI_FAILURE

137
configure vendored
View File

@ -17851,7 +17851,7 @@ esac
fi fi
done done
for ac_func in snprintf vsnprintf asprintf vasprintf for ac_func in snprintf vsnprintf
do : do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -17860,11 +17860,134 @@ if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF _ACEOF
else
NEED_SNPRINTF=1
fi fi
done done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working snprintf" >&5
$as_echo_n "checking for working snprintf... " >&6; }
if ${ac_cv_have_working_snprintf+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_have_working_snprintf=cross
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int main(void)
{
char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
int i;
i = snprintf (bufs, 2, "%s", "111");
if (strcmp (bufs, "1")) exit (1);
if (i != 3) exit (1);
i = snprintf (bufd, 2, "%d", 111);
if (strcmp (bufd, "1")) exit (1);
if (i != 3) exit (1);
exit(0);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_have_working_snprintf=yes
else
ac_cv_have_working_snprintf=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_working_snprintf" >&5
$as_echo "$ac_cv_have_working_snprintf" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vsnprintf" >&5
$as_echo_n "checking for working vsnprintf... " >&6; }
if ${ac_cv_have_working_vsnprintf+:} false; then :
$as_echo_n "(cached) " >&6
else
if test "$cross_compiling" = yes; then :
ac_cv_have_working_vsnprintf=cross
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <stdarg.h>
int my_vsnprintf (char *buf, const char *tmpl, ...)
{
int i;
va_list args;
va_start (args, tmpl);
i = vsnprintf (buf, 2, tmpl, args);
va_end (args);
return i;
}
int main(void)
{
char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
int i;
i = my_vsnprintf (bufs, "%s", "111");
if (strcmp (bufs, "1")) exit (1);
if (i != 3) exit (1);
i = my_vsnprintf (bufd, "%d", 111);
if (strcmp (bufd, "1")) exit (1);
if (i != 3) exit (1);
exit(0);
}
_ACEOF
if ac_fn_c_try_run "$LINENO"; then :
ac_cv_have_working_vsnprintf=yes
else
ac_cv_have_working_vsnprintf=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_working_vsnprintf" >&5
$as_echo "$ac_cv_have_working_vsnprintf" >&6; }
if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes"; then
case " $LIBOBJS " in
*" snprintf.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Replacing missing/broken (v)snprintf() with sudo's version." >&5
$as_echo "$as_me: WARNING: Replacing missing/broken (v)snprintf() with sudo's version." >&2;}
$as_echo "#define PREFER_PORTABLE_SNPRINTF 1" >>confdefs.h
fi
for ac_func in asprintf vasprintf
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"; then
# Don't add snprintf to LIBOBJS if it is already present.
if test X"$ac_cv_func_asprintf$ac_cv_func_vasprintf" != X"yesyes"; then
case " $LIBOBJS " in
*" snprintf.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
;;
esac
fi
fi
if test X"$ac_cv_type_struct_timespec" != X"no"; then if test X"$ac_cv_type_struct_timespec" != X"no"; then
ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default" ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim" "ac_cv_member_struct_stat_st_mtim" "$ac_includes_default"
if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then : if test "x$ac_cv_member_struct_stat_st_mtim" = xyes; then :
@ -18174,14 +18297,6 @@ _ACEOF
fi fi
if test -n "$NEED_SNPRINTF"; then
case " $LIBOBJS " in
*" snprintf.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
;;
esac
fi
ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket"
if test "x$ac_cv_func_socket" = xyes; then : if test "x$ac_cv_func_socket" = xyes; then :

View File

@ -2401,7 +2401,14 @@ AC_CHECK_FUNCS(mkstemps mkdtemp, [], [
AC_CHECK_FUNCS(random lrand48, [break]) AC_CHECK_FUNCS(random lrand48, [break])
AC_LIBOBJ(mktemp) AC_LIBOBJ(mktemp)
]) ])
AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf, , [NEED_SNPRINTF=1]) AX_FUNC_SNPRINTF
AC_CHECK_FUNCS(asprintf vasprintf)
if test X"$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf" = X"yesyes"; then
# Don't add snprintf to LIBOBJS if it is already present.
if test X"$ac_cv_func_asprintf$ac_cv_func_vasprintf" != X"yesyes"; then
AC_LIBOBJ(snprintf)
fi
fi
if test X"$ac_cv_type_struct_timespec" != X"no"; then if test X"$ac_cv_type_struct_timespec" != X"no"; then
AC_CHECK_MEMBER([struct stat.st_mtim], [AC_DEFINE(HAVE_ST_MTIM)] AC_CHECK_MEMBER([struct stat.st_mtim], [AC_DEFINE(HAVE_ST_MTIM)]
[AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))], [AC_CHECK_MEMBER([struct stat.st_mtim.st__tim], AC_DEFINE(HAVE_ST__TIM))],
@ -2466,13 +2473,6 @@ AC_INCLUDES_DEFAULT
#include <$ac_header_dirent> #include <$ac_header_dirent>
]) ])
dnl dnl
dnl If NEED_SNPRINTF is set, add snprintf.c to LIBOBJS
dnl (it contains snprintf, vsnprintf, asprintf, and vasprintf)
dnl
if test -n "$NEED_SNPRINTF"; then
AC_LIBOBJ(snprintf)
fi
dnl
dnl If socket(2) not in libc, check -lsocket and -linet dnl If socket(2) not in libc, check -lsocket and -linet
dnl May need to link with *both* -lnsl and -lsocket due to unresolved symbols dnl May need to link with *both* -lnsl and -lsocket due to unresolved symbols
dnl dnl

82
m4/ax_func_snprintf.m4 Normal file
View File

@ -0,0 +1,82 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_func_snprintf.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_FUNC_SNPRINTF
#
# DESCRIPTION
#
# Checks for a fully C99 compliant snprintf, in particular checks whether
# it does bounds checking and returns the correct string length; does the
# same check for vsnprintf. If no working snprintf or vsnprintf is found,
# request a replacement and warn the user about it. Note: the mentioned
# replacement is freely available and may be used in any project
# regardless of it's license.
#
# LICENSE
#
# Copyright (c) 2008 Ruediger Kuhlmann <info@ruediger-kuhlmann.de>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 5
AC_DEFUN([AX_FUNC_SNPRINTF],
[AC_CHECK_FUNCS(snprintf vsnprintf)
AC_MSG_CHECKING(for working snprintf)
AC_CACHE_VAL(ac_cv_have_working_snprintf,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>
int main(void)
{
char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
int i;
i = snprintf (bufs, 2, "%s", "111");
if (strcmp (bufs, "1")) exit (1);
if (i != 3) exit (1);
i = snprintf (bufd, 2, "%d", 111);
if (strcmp (bufd, "1")) exit (1);
if (i != 3) exit (1);
exit(0);
}]])],[ac_cv_have_working_snprintf=yes],[ac_cv_have_working_snprintf=no],[ac_cv_have_working_snprintf=cross])])
AC_MSG_RESULT([$ac_cv_have_working_snprintf])
AC_MSG_CHECKING(for working vsnprintf)
AC_CACHE_VAL(ac_cv_have_working_vsnprintf,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>
#include <stdarg.h>
int my_vsnprintf (char *buf, const char *tmpl, ...)
{
int i;
va_list args;
va_start (args, tmpl);
i = vsnprintf (buf, 2, tmpl, args);
va_end (args);
return i;
}
int main(void)
{
char bufs[5] = { 'x', 'x', 'x', '\0', '\0' };
char bufd[5] = { 'x', 'x', 'x', '\0', '\0' };
int i;
i = my_vsnprintf (bufs, "%s", "111");
if (strcmp (bufs, "1")) exit (1);
if (i != 3) exit (1);
i = my_vsnprintf (bufd, "%d", 111);
if (strcmp (bufd, "1")) exit (1);
if (i != 3) exit (1);
exit(0);
}]])],[ac_cv_have_working_vsnprintf=yes],[ac_cv_have_working_vsnprintf=no],[ac_cv_have_working_vsnprintf=cross])])
AC_MSG_RESULT([$ac_cv_have_working_vsnprintf])
if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes"; then
AC_LIBOBJ(snprintf)
AC_MSG_WARN([Replacing missing/broken (v)snprintf() with sudo's version.])
AC_DEFINE(PREFER_PORTABLE_SNPRINTF, 1, [Enable replacement (v)snprintf if system (v)snprintf is broken.])
fi])