From 8e9a8c043ef5b16a2f13999bd2c5d59d61dd00d1 Mon Sep 17 00:00:00 2001 From: nobu Date: Sun, 9 Sep 2018 07:49:04 +0000 Subject: util.c: qsort_s in C11 * configure.ac: macro for C11 to use qsort_s. * util.c (ruby_qsort): fix for C11 qsort_s. the comparison function for MSVCRT qsort_s is compatible with BSD qsort_r, but not with C11 qsort_s, in spite of its name. note that mingw defines __STDC_VERSION__ but uses qsort_s in MSVCRT, so the MSVCRT block needs to preced the C11 block. [ruby-core:88899] [Bug #15091] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64661 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- configure.ac | 2 +- util.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index b8ee572392..8e185a6e3c 100644 --- a/configure.ac +++ b/configure.ac @@ -1869,7 +1869,7 @@ AC_CHECK_FUNCS(utimes) AC_CHECK_FUNCS(wait4) AC_CHECK_FUNCS(waitpid) -AS_IF([test "$ac_cv_func_memset_s" = yes], +AS_CASE(["$ac_cv_func_memset_s:$ac_cvs_func_qsort_s"], [*yes*], [RUBY_DEFINE_IF([!defined __STDC_WANT_LIB_EXT1__], [__STDC_WANT_LIB_EXT1__], 1)]) AS_IF([test "$ac_cv_func_getcwd" = yes], [ diff --git a/util.c b/util.c index 2c1ae8600c..a713086de0 100644 --- a/util.c +++ b/util.c @@ -195,14 +195,32 @@ ruby_strtoul(const char *str, char **endptr, int base) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif -#if !defined HAVE_BSD_QSORT_R && defined HAVE_QSORT_S +typedef int (cmpfunc_t)(const void*, const void*, void*); + +#if defined HAVE_QSORT_S +# if defined __MSVCRT__ # define qsort_r(base, nel, size, arg, cmp) qsort_s(base, nel, size, cmp, arg) # define cmp_bsd_qsort cmp_ms_qsort # define HAVE_BSD_QSORT_R 1 +# elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L +/* C11 qsort_s has the same arguments as ours */ +void +ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d) +{ + if (!nel || !size) return; /* nothing to sort */ + + /* get rid of runtime-constraints handler for MT-safeness */ + if (!base || !cmp) return; + if (nel > RSIZE_MAX || size > RSIZE_MAX) return; + + qsort_s(base, nel, size, cmp, d); +} +# else +# error Unknown version qsort_s +# endif #endif -#if defined HAVE_BSD_QSORT_R -typedef int (cmpfunc_t)(const void*, const void*, void*); +#if defined HAVE_BSD_QSORT_R struct bsd_qsort_r_args { cmpfunc_t *cmp; void *arg; @@ -339,7 +357,6 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */ ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \ ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c)))) -typedef int (cmpfunc_t)(const void*, const void*, void*); void ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d) { -- cgit v1.2.3