Skip to content

Commit

Permalink
build: handle enforced 64 bit offsets for controlled ABI break
Browse files Browse the repository at this point in the history
git-svn-id: svn://scm.orgis.org/mpg123/trunk@5415 35dc7657-300d-0410-a2e5-dc2837fedb53
  • Loading branch information
thor committed Apr 2, 2024
1 parent e87e3fd commit 446e6ee
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 9 deletions.
9 changes: 9 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
1.32.6
------
- build: Detect forced 64 bit offsets on a dual-mode system that used
to default to 32 bits and drop ambiguous suffix-less symbols in that
case. This avoids subtle ABI breakage (causing memory corruption)
with existing binaries and instead has them fail during runtime linking.
You trigger that when having -D_FILE_OFFSET_BITS=64 in your compiler
flags during mpg123 build.

1.32.5
------

Expand Down
26 changes: 24 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1355,8 +1355,13 @@ AC_COMPUTE_INT(switched_off_size, sizeof(off_t), [
#include <sys/types.h>
])
AC_MSG_RESULT([$switched_off_size])
# If you have predefined _FILE_OFFSET_BITS, I will treat that as a system
# property.
AC_MSG_CHECKING([unswitched off_t size])
AC_COMPUTE_INT(unswitched_off_size, sizeof(off_t), [
#undef _FILE_OFFSET_BITS
#include <sys/types.h>
])
AC_MSG_RESULT([$unswitched_off_size])
# Now the size without meddling, possibly enforced to 64 bits by system settings.
AC_CHECK_SIZEOF(off_t, [], [
#include <sys/types.h>
])
Expand All @@ -1381,6 +1386,15 @@ else
lfs_sensitive=no
fi

forced_off_64=no
if test "x$unswitched_off_size" != "x$ac_cv_sizeof_off_t"; then
if test "x$ac_cv_sizeof_off_t" = x8; then
AC_MSG_NOTICE([Detected system with enforced 64 bit offsets, dropping suffixless symbols for uncryptic ABI breakage.])
AC_DEFINE([FORCED_OFF_64], 1, [System setup enforces 64 bit offsets where 32 bit would be native.])
forced_off_64=yes
fi
fi

use_largefile=auto

AC_MSG_CHECKING([if native off_t is already 64 bits])
Expand Down Expand Up @@ -2969,8 +2983,16 @@ fi
echo " largefile sensitive ..... $lfs_sensitive"
echo " default offsets ......... $default_offset_bits"
echo " explicit 64 bit offsets . $use_largefile"
echo " forced 64 bit offsets ... $forced_off_64"
echo " only portable API ....... $portable_api"

if test "x$forced_off_64" = xyes; then
echo
echo "Note: Ensure that client programs are built with _FILE_OFFSET_BITS defined to 64, too."
echo " Old binaries built for 32 bit off_t may fail missing symbols in mpg123 libraries."
echo
fi

echo "
Core libmpg123 features:
Layer I ................. $layer1
Expand Down
21 changes: 21 additions & 0 deletions src/libmpg123/lfs_wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ static struct wrap_data* wrap_get(mpg123_handle *mh, int force_alloc)
/* After settling the data... start with some simple wrappers. */

// The fist block of wrappers is always present, using the native off_t width.
// (Exception: If explicitly disabled using FORCED_OFF_64.)
// A second block mirrors that in case of sizeof(off_t)==4 with _32 suffix.
// A third block follows if 64 bit off_t is available with _64 suffix, just aliasing
// the int64_t functions.

#ifndef FORCED_OFF_64

#define OFF_CONV(value, variable, handle) \
if((value) >= OFF_MIN && (value) <= OFF_MAX) \
variable = (off_t)(value); \
Expand Down Expand Up @@ -399,6 +402,8 @@ int attribute_align_arg mpg123_position( mpg123_handle *mh, off_t INT123_frame_o
return MPG123_OK;
}

#endif // FORCED_OFF_64

// _32 aliases only for native 32 bit off_t
// Will compilers be smart enough to optimize away the extra function call?
#if SIZEOF_OFF_T == 4
Expand Down Expand Up @@ -523,6 +528,10 @@ int attribute_align_arg mpg123_position_32( mpg123_handle *mh, off_t INT123_fram
#define OFF64 off_t
#endif

#ifndef FORCED_OFF_64
// When 64 bit offsets are enforced, libmpg123.c defines the _64 functions directly.
// There is no actual wrapper work, anyway.

int attribute_align_arg mpg123_open_64(mpg123_handle *mh, const char *path)
{
return mpg123_open(mh, path);
Expand All @@ -543,6 +552,8 @@ int attribute_align_arg mpg123_open_handle_64(mpg123_handle *mh, void *iohandle)
{
return mpg123_open_handle(mh, iohandle);
}
#endif


int attribute_align_arg mpg123_framebyframe_decode_64(mpg123_handle *mh, OFF64 *num, unsigned char **audio, size_t *bytes)
{
Expand Down Expand Up @@ -860,6 +871,13 @@ static mpg123_ssize_t fallback_read(int fd, void *buf, size_t count)
return read(fd, buf, count);
}

// In forced 64 bit offset mode, the only definitions of these are
// the _64 ones.
#ifdef FORCED_OFF_64
#define mpg123_replace_reader mpg123_replace_reader_64
#define mpg123_replace_reader_handle mpg123_replace_reader_handle_64
#endif

/* Reader replacement prepares the hidden handle storage for next mpg123_open_fd() or plain mpg123_open(). */
int attribute_align_arg mpg123_replace_reader(mpg123_handle *mh, mpg123_ssize_t (*r_read) (int, void *, size_t), off_t (*r_lseek)(int, off_t, int) )
{
Expand Down Expand Up @@ -978,6 +996,8 @@ int attribute_align_arg mpg123_replace_reader_handle_64(mpg123_handle *mh, mpg12

#elif SIZEOF_OFF_T == 8

// If 64 bit off_t is enforced, libmpg123.c already defines the _64 functions.
#ifndef FORCED_OFF_64
int attribute_align_arg mpg123_replace_reader_64(mpg123_handle *mh, mpg123_ssize_t (*r_read) (int, void *, size_t), off_t (*r_lseek)(int, off_t, int) )
{
return mpg123_replace_reader(mh, r_read, r_lseek);
Expand All @@ -987,5 +1007,6 @@ int attribute_align_arg mpg123_replace_reader_handle_64(mpg123_handle *mh, mpg12
{
return mpg123_replace_reader_handle(mh, r_read, r_lseek, cleanup);
}
#endif

#endif
17 changes: 14 additions & 3 deletions src/libmpg123/libmpg123.c
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,15 @@ double attribute_align_arg mpg123_geteq2(mpg123_handle *mh, int channel, int ban
}

#ifndef PORTABLE_API

#ifdef FORCED_OFF_64
// Only _64 symbols for a system-wide enforced _FILE_OFFSET_BITS=64.
#define mpg123_open mpg123_open_64
#define mpg123_open_fixed mpg123_open_fixed_64
#define mpg123_open_fd mpg123_open_fd_64
#define mpg123_open_handle mpg123_open_handle_64
#endif

/* plain file access, no http! */
int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
{
Expand All @@ -579,7 +588,9 @@ int attribute_align_arg mpg123_open(mpg123_handle *mh, const char *path)
// The convenience function mpg123_open_fixed() wraps over acual mpg123_open
// and hence needs to have the exact same code in lfs_wrap.c. The flesh is
// in INT123_open_fixed_pre() and INT123_open_fixed_post(), wich are only defined here.
int INT123_open_fixed_pre(mpg123_handle *mh, int channels, int encoding)
// Update: The open routines are just alias calls now, since the conversion to
// int64_t internally.
static int INT123_open_fixed_pre(mpg123_handle *mh, int channels, int encoding)
{
if(!mh)
return MPG123_BAD_HANDLE;
Expand All @@ -590,7 +601,7 @@ int INT123_open_fixed_pre(mpg123_handle *mh, int channels, int encoding)
return err;
}

int INT123_open_fixed_post(mpg123_handle *mh, int channels, int encoding)
static int INT123_open_fixed_post(mpg123_handle *mh, int channels, int encoding)
{
if(!mh)
return MPG123_BAD_HANDLE;
Expand Down Expand Up @@ -637,7 +648,7 @@ int attribute_align_arg mpg123_open_fd(mpg123_handle *mh, int fd)
ret = INT123_open_stream_handle(mh, mh->wrapperdata);
return ret;
}
#endif
#endif // PORTABLE_API

int attribute_align_arg mpg123_open_handle(mpg123_handle *mh, void *iohandle)
{
Expand Down
3 changes: 0 additions & 3 deletions src/libmpg123/mpg123lib_intern.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,6 @@ int64_t INT123_outblock_bytes(mpg123_handle *fr, int64_t s);
/* Postprocessing format conversion of freshly decoded buffer. */
void INT123_postprocess_buffer(mpg123_handle *fr);

int INT123_open_fixed_pre(mpg123_handle *mh, int channels, int encoding);
int INT123_open_fixed_post(mpg123_handle *mh, int channels, int encoding);

/* If networking is enabled and we really mean internal networking, the timeout_read function is available. */
#if defined (NETWORK) && !defined (WANT_WIN32_SOCKETS)
/* Does not work with win32 */
Expand Down
2 changes: 2 additions & 0 deletions src/libsyn123/resample.c
Original file line number Diff line number Diff line change
Expand Up @@ -2038,8 +2038,10 @@ type attribute_align_arg name(long inrate, long outrate, type io) \
}

#if SIZEOF_OFF_T == 8
#ifndef FORCED_OFF_64
resample_total_alias(off_t, syn123_resample_total, syn123_resample_total64)
resample_total_alias(off_t, syn123_resample_intotal, syn123_resample_intotal64)
#endif
resample_total_alias(off_t, syn123_resample_total_64, syn123_resample_total64)
resample_total_alias(off_t, syn123_resample_intotal_64, syn123_resample_intotal64)
#elif SIZEOF_OFF_T == 4
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// only single spaces as separator to ease parsing by build scripts
#define MPG123_MAJOR 1
#define MPG123_MINOR 32
#define MPG123_PATCH 5
#define MPG123_PATCH 6
// Don't get too wild with that to avoid confusing m4. No brackets.
// Also, it should fit well into a sane file name for the tarball.
#define MPG123_SUFFIX "-dev"
Expand Down

0 comments on commit 446e6ee

Please sign in to comment.