From: Bruno Haible Date: Tue, 2 Jan 2024 10:37:05 +0000 (+0100) Subject: strverscmp: Work around bug in musl libc 1.2.3 and in Cygwin. X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=6fbd739e3958fc08c5b0a72319eb91b5c702ab59;p=gnulib.git strverscmp: Work around bug in musl libc 1.2.3 and in Cygwin. Reported by Dmitry Bogatov via Simon Josefsson in . * m4/string_h.m4 (gl_STRING_H_DEFAULTS): Initialize REPLACE_STRVERSCMP. * m4/strverscmp.m4 (gl_FUNC_STRVERSCMP): Test whether strverscmp works and set REPLACE_STRVERSCMP if not. * lib/string.in.h (strverscmp): Consider REPLACE_STRVERSCMP. * modules/strverscmp (Depends-on, configure.ac): Likewise. * modules/string (Makefile.am): Substitute REPLACE_STRVERSCMP. * tests/test-strverscmp.c (main): Add test cases suggested by Dmitry Bogatov and by Simon Josefsson. * doc/glibc-functions/strverscmp.texi: Mention the musl and Cygwin bug. Update version info regarding FreeBSD. --- diff --git a/ChangeLog b/ChangeLog index fc728584f7..6715a9e9b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2024-01-02 Bruno Haible + + strverscmp: Work around bug in musl libc 1.2.3 and in Cygwin. + Reported by Dmitry Bogatov via Simon Josefsson in + . + * m4/string_h.m4 (gl_STRING_H_DEFAULTS): Initialize REPLACE_STRVERSCMP. + * m4/strverscmp.m4 (gl_FUNC_STRVERSCMP): Test whether strverscmp works + and set REPLACE_STRVERSCMP if not. + * lib/string.in.h (strverscmp): Consider REPLACE_STRVERSCMP. + * modules/strverscmp (Depends-on, configure.ac): Likewise. + * modules/string (Makefile.am): Substitute REPLACE_STRVERSCMP. + * tests/test-strverscmp.c (main): Add test cases suggested by Dmitry + Bogatov and by Simon Josefsson. + * doc/glibc-functions/strverscmp.texi: Mention the musl and Cygwin bug. + Update version info regarding FreeBSD. + 2024-01-01 Paul Eggert update-copyright-tests: immunize against self diff --git a/doc/glibc-functions/strverscmp.texi b/doc/glibc-functions/strverscmp.texi index 5882d223e1..9e37143fa4 100644 --- a/doc/glibc-functions/strverscmp.texi +++ b/doc/glibc-functions/strverscmp.texi @@ -20,8 +20,13 @@ Gnulib module: strverscmp Portability problems fixed by Gnulib: @itemize @item -This function is missing on all non-glibc platforms: -macOS 11.1, FreeBSD 13.0, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android 9.0. +This function is missing on many platforms: +macOS 11.1, FreeBSD 13.1, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, Solaris 11.4, Cygwin 1.7.x, mingw, MSVC 14, Android 9.0. +@item +This function treats ASCII letters as smaller than a digit sequence +on some platforms: +@c https://git.musl-libc.org/cgit/musl/commit/src/string/strverscmp.c?id=b50eb8c36c20f967bd0ed70c0b0db38a450886ba +musl libc 1.2.3, Cygwin 3.4.6. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/string.in.h b/lib/string.in.h index 66be871a57..01ea3e3913 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -1419,12 +1419,22 @@ _GL_WARN_ON_USE (strsignal, "strsignal is unportable - " #endif #if @GNULIB_STRVERSCMP@ -# if !@HAVE_STRVERSCMP@ +# if @REPLACE_STRVERSCMP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define strverscmp rpl_strverscmp +# endif +_GL_FUNCDECL_RPL (strverscmp, int, (const char *, const char *) + _GL_ATTRIBUTE_PURE + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strverscmp, int, (const char *, const char *)); +# else +# if !@HAVE_STRVERSCMP@ _GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) _GL_ATTRIBUTE_PURE _GL_ARG_NONNULL ((1, 2))); -# endif +# endif _GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); +# endif _GL_CXXALIASWARN (strverscmp); #elif defined GNULIB_POSIXCHECK # undef strverscmp diff --git a/m4/string_h.m4 b/m4/string_h.m4 index 3cbcbc7487..8b12101447 100644 --- a/m4/string_h.m4 +++ b/m4/string_h.m4 @@ -5,7 +5,7 @@ # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 37 +# serial 38 # Written by Paul Eggert. @@ -146,5 +146,6 @@ AC_DEFUN([gl_STRING_H_DEFAULTS], REPLACE_STRERROR_R=0; AC_SUBST([REPLACE_STRERROR_R]) REPLACE_STRERRORNAME_NP=0; AC_SUBST([REPLACE_STRERRORNAME_NP]) REPLACE_STRSIGNAL=0; AC_SUBST([REPLACE_STRSIGNAL]) + REPLACE_STRVERSCMP=0; AC_SUBST([REPLACE_STRVERSCMP]) UNDEFINE_STRTOK_R=0; AC_SUBST([UNDEFINE_STRTOK_R]) ]) diff --git a/m4/strverscmp.m4 b/m4/strverscmp.m4 index a0eef7bd92..748272abec 100644 --- a/m4/strverscmp.m4 +++ b/m4/strverscmp.m4 @@ -1,4 +1,4 @@ -# strverscmp.m4 serial 9 +# strverscmp.m4 serial 10 dnl Copyright (C) 2002, 2005-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -13,6 +13,37 @@ AC_DEFUN([gl_FUNC_STRVERSCMP], AC_CHECK_FUNCS([strverscmp]) if test $ac_cv_func_strverscmp = no; then HAVE_STRVERSCMP=0 + else + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether strverscmp works], + [gl_cv_func_strverscmp_works], + [dnl Detect musl-1.2.3 and Cygwin 3.4.6 bug. + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +int main () +{ + return strverscmp ("UNKNOWN", "2.2.0") <= 0; +} + ]])], + [gl_cv_func_strverscmp_works=yes], + [gl_cv_func_strverscmp_works=no], + [case "$host_os" in + # Guess yes on glibc systems. + *-gnu* | gnu*) gl_cv_func_strverscmp_works="guessing yes" ;; + # Guess no on musl systems. + *-musl* | midipix*) gl_cv_func_strverscmp_works="guessing no" ;; + # Guess no on Cygwin. + cygwin*) gl_cv_func_strverscmp_works="guessing no" ;; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_strverscmp_works="$gl_cross_guess_normal" ;; + esac + ]) + ]) + case "$gl_cv_func_strverscmp_works" in + *yes) ;; + *) REPLACE_STRVERSCMP=1 ;; + esac fi ]) diff --git a/modules/string b/modules/string index 8fbcc542c5..acbd614dcd 100644 --- a/modules/string +++ b/modules/string @@ -125,6 +125,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_STRERROR_R''@|$(REPLACE_STRERROR_R)|g' \ -e 's|@''REPLACE_STRERRORNAME_NP''@|$(REPLACE_STRERRORNAME_NP)|g' \ -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ + -e 's|@''REPLACE_STRVERSCMP''@|$(REPLACE_STRVERSCMP)|g' \ -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ diff --git a/modules/strverscmp b/modules/strverscmp index a80d1dd1d7..f4f76c7d0c 100644 --- a/modules/strverscmp +++ b/modules/strverscmp @@ -7,13 +7,14 @@ m4/strverscmp.m4 Depends-on: extensions -libc-config [test $HAVE_STRVERSCMP = 0] -stdint [test $HAVE_STRVERSCMP = 0] +libc-config [test $HAVE_STRVERSCMP = 0 || test $REPLACE_STRVERSCMP = 1] +stdint [test $HAVE_STRVERSCMP = 0 || test $REPLACE_STRVERSCMP = 1] string configure.ac: gl_FUNC_STRVERSCMP -gl_CONDITIONAL([GL_COND_OBJ_STRVERSCMP], [test $HAVE_STRVERSCMP = 0]) +gl_CONDITIONAL([GL_COND_OBJ_STRVERSCMP], + [test $HAVE_STRVERSCMP = 0 || test $REPLACE_STRVERSCMP = 1]) AM_COND_IF([GL_COND_OBJ_STRVERSCMP], [ gl_PREREQ_STRVERSCMP ]) diff --git a/tests/test-strverscmp.c b/tests/test-strverscmp.c index a7fbcdb993..2706572bc6 100644 --- a/tests/test-strverscmp.c +++ b/tests/test-strverscmp.c @@ -30,6 +30,7 @@ main (void) { ASSERT (strverscmp ("", "") == 0); ASSERT (strverscmp ("a", "a") == 0); + ASSERT (strverscmp ("1.7", "1.7") == 0); ASSERT (strverscmp ("a", "b") < 0); ASSERT (strverscmp ("b", "a") > 0); ASSERT (strverscmp ("000", "00") < 0); @@ -55,5 +56,13 @@ main (void) ASSERT (strverscmp (c, a) > 0); } + /* From Dmitry Bogatov. */ + { + static char const a[] = "UNKNOWN"; + static char const b[] = "2.2.0"; + ASSERT (strverscmp (a, b) > 0); + ASSERT (strverscmp (b, a) < 0); + } + return 0; }