|author||Sergey Poznyakoff <firstname.lastname@example.org>||2019-11-16 09:13:08 +0200|
|committer||Sergey Poznyakoff <email@example.com>||2019-11-16 09:13:08 +0200|
Fix handling of device numbers (part 2)
Previously the members of cpio_file_stat that hold device major and minor numbers were signed (long). This caused issues when the device number was cast to unsigned value (uintmax_t) during a call to to_ascii or derived function. In particular, on *BSD systems minor numbers are negative ints. When such numbers are passed to to_ascii, the resulting unsigned representation does not fit into the target field width. For details, see https://lists.gnu.org/archive/html/bug-cpio/2019-11/msg00012.html To fix this, the return types are autodetected by configure. The types of the c_dev_maj, c_dev_min, c_rdev_maj, and c_rdev_min members of struct cpio_file_stat are changed to unsigned versions of the corresponding detected types. This ensures that the value returned from major (or minor) will not undergo sign extension during assignment to the struct member and can be correctly promoted to a wider unsigned data type. * am/ax_compile_check_rettype.m4: New macro AC_COMPILE_CHECK_RETTYPE * configure.ac: Detect return types of major(3) and minor(3). * src/cpiohdr.h (cpio_file_stat): Change types of c_dev_maj, c_dev_min, c_rdev_maj, c_rdev_min.
3 files changed, 92 insertions, 4 deletions
diff --git a/am/ax_compile_check_rettype.m4 b/am/ax_compile_check_rettype.m4
new file mode 100644
@@ -0,0 +1,86 @@
+# AC_COMPILE_RETTYPE(FUNC, ARGS [, HEADERS [, EXTRA_TYPES...]])
+# This macro finds the integer type that can be used to represent the
+# value returned by FUNC (a C function or define). It uses only
+# compile checks (AC_COMPILE_IFELSE) and is safe to use when cross-
+# compiling. The ARGS parameter gives arguments to supply to the
+# function call. Obviously, these must be immediate values.
+# HEADERS supplies additional headers to include.
+# If a matching integer type was found, the macro defines
+# RETTYPE_`TYPE' to its name. Otherwise, an error is reported.
+# AC_COMPILE_RETTYPE(major, 0)
+# The macro is derived from AX_COMPILE_CHECK_SIZEOF:
+# Copyright (c) 2008 Kaveh Ghazi <firstname.lastname@example.org>
+# Copyright (c) 2017 Reini Urban <email@example.com>
+# Copyright (c) 2019 Sergey Poznyakoff <firstname.lastname@example.org>
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(RETTYPE_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_rettype_$1, [ *], [_p]))dnl
+AC_MSG_CHECKING(return type of $1())
+[for ac_type in char short int long "long long" $4
+]], [[switch (0) case 0: case (sizeof ($1($2)) == sizeof ($ac_type)):;]])], [AC_CV_NAME=$ac_type])
+ if test x$AC_CV_NAME != x ; then break; fi
+if test x$AC_CV_NAME = x ; then
+ AC_MSG_ERROR([cannot determine type])
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [Data type returned by $1()])
diff --git a/configure.ac b/configure.ac
index 2132256..5f446a7 100644
@@ -45,6 +45,8 @@ AC_TYPE_UID_T
# This is needed for mingw build
diff --git a/src/cpiohdr.h b/src/cpiohdr.h
index ff5f375..4056045 100644
@@ -119,10 +119,10 @@ struct cpio_file_stat /* Internal representation of a CPIO header */
- long c_dev_maj;
- long c_dev_min;
- long c_rdev_maj;
- long c_rdev_min;
+ unsigned RETTYPE_MAJOR c_dev_maj;
+ unsigned RETTYPE_MINOR c_dev_min;
+ unsigned RETTYPE_MAJOR c_rdev_maj;
+ unsigned RETTYPE_MINOR c_rdev_min;