Ticket #3617: 3617-mc_open-handle-varargs-mode_t-promotion-issue--v2.patch

File 3617-mc_open-handle-varargs-mode_t-promotion-issue--v2.patch, 3.9 KB (added by mooffie, 8 years ago)
  • acinclude.m4

    From 6b18b06ecf07a9f9b0500f5b72ff449b8723e7ba Mon Sep 17 00:00:00 2001
    From: Mooffie <mooffie@gmail.com>
    Date: Wed, 16 Mar 2016 17:10:48 +0200
    Subject: [PATCH] Ticket #3617: (mc_open): handle varargs mode_t promotion
    On systems where 'mode_t' is smaller than 'int', doing 'va_arg (ap, mode_t)' is
    wrong because of C's "default argument promotions". GCC 4 creates crashing code
    in this case.
    The "va_arg" page of Gnulib's manual describes the problem and a simple solution:
    However, since that solution reportedly (see thread at next link) still causes
    GCC to print warnings (for no good reason; perhaps this was fixed in newer
    GCCs), we pick a solution that defines a PROMOTED_MODE_T at the configuration
    (We take our 'mode_t.m4' from the most recent Gnulib source.)
    (If any of the URLs above no longer works, simply search the web for the
    mentioned words.)
     acinclude.m4         |  1 +
     configure.ac         |  1 +
     lib/vfs/interface.c  |  5 ++++-
     m4.include/mode_t.m4 | 26 ++++++++++++++++++++++++++
     4 files changed, 32 insertions(+), 1 deletion(-)
     create mode 100644 m4.include/mode_t.m4
    diff --git a/acinclude.m4 b/acinclude.m4
    index f228cd7..861ca22 100644
    a b m4_include([m4.include/ax_path_lib_pcre.m4]) 
  • configure.ac

    diff --git a/configure.ac b/configure.ac
    index 4962f03..d0d8358 100644
    a b AC_CHECK_SIZEOF(uintmax_t) 
  • lib/vfs/interface.c

    diff --git a/lib/vfs/interface.c b/lib/vfs/interface.c
    index 64acb96..53934c0 100644
    a b mc_open (const vfs_path_t * vpath, int flags, ...) 
    200200    { 
    201201        va_list ap; 
    202202        va_start (ap, flags); 
    203         mode = va_arg (ap, mode_t); 
     203        /* We have to use PROMOTED_MODE_T instead of mode_t. Doing 'va_arg (ap, mode_t)' 
     204         * fails on systems where 'mode_t' is smaller than 'int' because of C's "default 
     205         * argument promotions". */ 
     206        mode = va_arg (ap, PROMOTED_MODE_T); 
    204207        va_end (ap); 
    205208    } 
  • new file m4.include/mode_t.m4

    diff --git a/m4.include/mode_t.m4 b/m4.include/mode_t.m4
    new file mode 100644
    index 0000000..0cd40db
    - +  
     1# mode_t.m4 serial 2 
     2dnl Copyright (C) 2009-2016 Free Software Foundation, Inc. 
     3dnl This file is free software; the Free Software Foundation 
     4dnl gives unlimited permission to copy and/or distribute it, 
     5dnl with or without modifications, as long as this notice is preserved. 
     7# For using mode_t, it's sufficient to use AC_TYPE_MODE_T and 
     8# include <sys/types.h>. 
     10# Define PROMOTED_MODE_T to the type that is the result of "default argument 
     11# promotion" (ISO C of the type mode_t. 
     15  AC_CACHE_CHECK([for promoted mode_t type], [gl_cv_promoted_mode_t], [ 
     16    dnl Assume mode_t promotes to 'int' if and only if it is smaller than 'int', 
     17    dnl and to itself otherwise. This assumption is not guaranteed by the ISO C 
     18    dnl standard, but we don't know of any real-world counterexamples. 
     19    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>]], 
     20      [[typedef int array[2 * (sizeof (mode_t) < sizeof (int)) - 1];]])], 
     21      [gl_cv_promoted_mode_t='int'], 
     22      [gl_cv_promoted_mode_t='mode_t']) 
     23  ]) 
     24  AC_DEFINE_UNQUOTED([PROMOTED_MODE_T], [$gl_cv_promoted_mode_t], 
     25    [Define to the type that is the result of default argument promotions of type mode_t.])