[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[libmicrohttpd] 01/03: Implemented basement to work with unaligned data
From: |
gnunet |
Subject: |
[libmicrohttpd] 01/03: Implemented basement to work with unaligned data |
Date: |
Tue, 18 May 2021 19:27:29 +0200 |
This is an automated email from the git hooks/post-receive script.
karlson2k pushed a commit to branch master
in repository libmicrohttpd.
commit 89387e53fe9e5d876fb14f31eac5da7d690290ff
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
AuthorDate: Tue May 18 19:37:10 2021 +0300
Implemented basement to work with unaligned data
---
configure.ac | 50 +++++++++++++++++++++++++++
src/microhttpd/Makefile.am | 16 ++++-----
src/microhttpd/mhd_align.h | 75 +++++++++++++++++++++++++++++++++++++++++
src/microhttpd/mhd_bithelpers.h | 44 +++++++++++++++++++-----
4 files changed, 168 insertions(+), 17 deletions(-)
diff --git a/configure.ac b/configure.ac
index cfe3e554..0cf4e43f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -307,6 +307,56 @@ AS_IF([[test "x$inln_prfx" != "xnone"]],
AC_MSG_RESULT([[$inln_prfx]])
CFLAGS="$save_CFLAGS"
+AC_CHECK_HEADERS([stdalign.h], [], [], [AC_INCLUDES_DEFAULT])
+AC_CACHE_CHECK([[for C11 'alignof()' support]], [[mhd_cv_c_alignof]],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#ifdef HAVE_STDALIGN_H
+#include <stdalign.h>
+#endif
+ ]], [[
+#if (defined (__GNUC__) && __GNUC__ < 4 && __GNUC_MINOR__ < 9 && !
defined(__clang__)) || \
+ (defined (__clang__) && __clang_major__ < 8)
+/* GCC before 4.9 and clang before 8.0 have incorrect implementation of
'alignof()'
+ which returns preferred alignment instead of minimal required alignment */
+#error Compiler has incorrect implementation of alignof()
+choke me now
+#endif
+ int var1[(alignof(int) >= 2) ? 1 : -1];
+ int var2[alignof(unsigned int) - 1];
+ int var3[(alignof(char) > 0) ? 1 : -1];
+ int var4[(alignof(long) >= 4) ? 1 : -1];
+
+ /* Mute compiler warnings */
+ var1[0] = var2[0] = var3[0] = 0;
+ var4[0] = 1;
+ if (var1[0] + var2[0] + var3[0] == var4[0])
+ return 1;
+ ]])
+ ], [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#ifdef HAVE_STDALIGN_H
+#include <stdalign.h>
+#endif
+ ]], [[
+ /* Should fail if 'alignof()' works */
+ int var1[alignof(nonexisting_type) - 1];
+
+ /* Mute compiler warnings */
+ var1[0] = 1;
+ if (var1[0] + 1 == 1)
+ return 1;
+ ]])
+ ], [[mhd_cv_c_alignof='no']], [[mhd_cv_c_alignof='yes']])
+ ], [[mhd_cv_c_alignof='no']])
+ ])
+AS_VAR_IF([mhd_cv_c_alignof], ["yes"],
+ [AC_DEFINE([[HAVE_C_ALIGNOF]], [1], [Define to 1 if your compiler supports
'alignof()'])])
+
+
# Check system type
shutdown_trig_select='no'
AC_MSG_CHECKING([[for target host OS]])
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 84fe4f81..abcbeba7 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -59,7 +59,7 @@ libmicrohttpd_la_SOURCES = \
internal.c internal.h \
memorypool.c memorypool.h \
mhd_mono_clock.c mhd_mono_clock.h \
- mhd_limits.h mhd_byteorder.h \
+ mhd_limits.h \
sysfdsetsize.c sysfdsetsize.h \
mhd_str.c mhd_str.h \
mhd_send.h mhd_send.c \
@@ -138,7 +138,7 @@ endif
if ENABLE_DAUTH
libmicrohttpd_la_SOURCES += \
digestauth.c \
- mhd_bithelpers.h \
+ mhd_bithelpers.h mhd_byteorder.h mhd_align.h \
md5.c md5.h \
sha256.c sha256.h
endif
@@ -345,13 +345,13 @@ test_shutdown_poll_ignore_LDADD = \
endif
test_str_compare_SOURCES = \
- test_str.c test_helpers.h mhd_str.c
+ test_str.c test_helpers.h mhd_str.c mhd_str.h
test_str_to_value_SOURCES = \
- test_str.c test_helpers.h mhd_str.c
+ test_str.c test_helpers.h mhd_str.c mhd_str.h
test_str_token_SOURCES = \
- test_str_token.c mhd_str.c
+ test_str_token.c mhd_str.c mhd_str.h
test_http_reasons_SOURCES = \
test_http_reasons.c \
@@ -359,15 +359,15 @@ test_http_reasons_SOURCES = \
test_md5_SOURCES = \
test_md5.c test_helpers.h \
- md5.c md5.h mhd_bithelpers.h
+ md5.c md5.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
test_sha256_SOURCES = \
test_sha256.c test_helpers.h \
- sha256.c sha256.h mhd_bithelpers.h
+ sha256.c sha256.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
test_sha1_SOURCES = \
test_sha1.c test_helpers.h \
- sha1.c sha1.h mhd_bithelpers.h
+ sha1.c sha1.h mhd_bithelpers.h mhd_byteorder.h mhd_align.h
test_options_SOURCES = \
test_options.c
diff --git a/src/microhttpd/mhd_align.h b/src/microhttpd/mhd_align.h
new file mode 100644
index 00000000..4464b6cd
--- /dev/null
+++ b/src/microhttpd/mhd_align.h
@@ -0,0 +1,75 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2021 Karlson2k (Evgeny Grin)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library.
+ If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file microhttpd/mhd_align.h
+ * @brief types alignment macros
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_ALIGN_H
+#define MHD_ALIGN_H 1
+
+#include <stdint.h>
+#include "mhd_options.h"
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_C_ALIGNOF
+
+#ifdef HAVE_STDALIGN_H
+#include <stdalign.h>
+#endif
+
+#define _MHD_ALIGNOF(type) alignof(type)
+
+#endif /* HAVE_C_ALIGNOF */
+
+#ifdef offsetof
+#define _MHD_OFFSETOF(strct, membr) offsetof(strct, membr)
+#else /* ! offsetof */
+#define _MHD_OFFSETOF(strct, membr) (size_t)(((char*)&(((strct*)0)->membr)) - \
+ ((char*)((strct*)0)))
+#endif /* ! offsetof */
+
+/* Provide a limited set of alignment macros */
+/* The set could be extended as needed */
+#ifdef _MHD_ALIGNOF
+#define _MHD_UINT32_ALIGN _MHD_ALIGNOF(uint32_t)
+#define _MHD_UINT64_ALIGN _MHD_ALIGNOF(uint64_t)
+#else /* ! _MHD_ALIGNOF */
+struct _mhd_dummy_uint32_offset_test
+{
+ char dummy;
+ uint32_t ui32;
+};
+#define _MHD_UINT32_ALIGN \
+ _MHD_OFFSETOF(struct _mhd_dummy_uint32_offset_test, ui32)
+
+struct _mhd_dummy_uint64_offset_test
+{
+ char dummy;
+ uint32_t ui64;
+};
+#define _MHD_UINT32_ALIGN \
+ _MHD_OFFSETOF(struct _mhd_dummy_uint64_offset_test, ui64)
+#endif /* ! _MHD_ALIGNOF */
+
+#endif /* ! MHD_ALIGN_H */
diff --git a/src/microhttpd/mhd_bithelpers.h b/src/microhttpd/mhd_bithelpers.h
index c8c814ac..12e1a569 100644
--- a/src/microhttpd/mhd_bithelpers.h
+++ b/src/microhttpd/mhd_bithelpers.h
@@ -32,8 +32,13 @@
/* Declarations for VC & Clang/C2 built-ins */
#include <intrin.h>
#endif /* _MSC_FULL_VER */
+#include "mhd_options.h"
#include "mhd_assert.h"
#include "mhd_byteorder.h"
+#if _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN || _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
+#include "mhd_align.h"
+#endif /* _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN ||
+ _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN */
#ifndef __has_builtin
/* Avoid precompiler errors with non-clang */
@@ -158,15 +163,8 @@
* put native-endian 64-bit value64 to addr
* in big-endian mode.
*/
-#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
-#define _MHD_PUT_64BIT_BE(addr, value64) \
- ((*(uint64_t*) (addr)) = (uint64_t) (value64))
-#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
-#define _MHD_PUT_64BIT_BE(addr, value64) \
- ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
-#else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
-/* Endianness was not detected or non-standard like PDP-endian */
-#define _MHD_PUT_64BIT_BE(addr, value64) do { \
+/* Slow version that works with unaligned addr and with any bytes order */
+#define _MHD_PUT_64BIT_BE_SLOW(addr, value64) do { \
((uint8_t*) (addr))[7] = (uint8_t) ((uint64_t) (value64)); \
((uint8_t*) (addr))[6] = (uint8_t) (((uint64_t) (value64)) >> 8); \
((uint8_t*) (addr))[5] = (uint8_t) (((uint64_t) (value64)) >> 16); \
@@ -176,8 +174,32 @@
((uint8_t*) (addr))[1] = (uint8_t) (((uint64_t) (value64)) >> 48); \
((uint8_t*) (addr))[0] = (uint8_t) (((uint64_t) (value64)) >> 56); \
} while (0)
+#if _MHD_BYTE_ORDER == _MHD_BIG_ENDIAN
+#define _MHD_PUT_64BIT_BE(addr, value64) \
+ ((*(uint64_t*) (addr)) = (uint64_t) (value64))
+#elif _MHD_BYTE_ORDER == _MHD_LITTLE_ENDIAN
+#define _MHD_PUT_64BIT_BE(addr, value64) \
+ ((*(uint64_t*) (addr)) = _MHD_BYTES_SWAP64 (value64))
+#else /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
+/* Endianness was not detected or non-standard like PDP-endian */
+#define _MHD_PUT_64BIT_BE(addr, value64) _MHD_PUT_64BIT_BE_SLOW(addr, value64)
+/* Indicate that _MHD_PUT_64BIT_BE does not need aligned pointer */
+#define _MHD_PUT_64BIT_BE_UNALIGNED 1
#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
+/* Put result safely to unaligned address */
+_MHD_static_inline void
+_MHD_PUT_64BIT_BE_SAFE (void *dst, uint64_t value)
+{
+#ifndef _MHD_PUT_64BIT_BE_UNALIGNED
+ if (0 != ((uintptr_t) dst) % (_MHD_UINT64_ALIGN))
+ _MHD_PUT_64BIT_BE_SLOW (dst, value);
+ else
+#endif /* _MHD_BYTE_ORDER_IS_BIG_OR_LITTLE_ENDIAN */
+ _MHD_PUT_64BIT_BE (dst, value);
+}
+
+
/* _MHD_PUT_32BIT_BE (addr, value32)
* put native-endian 32-bit value32 to addr
* in big-endian mode.
@@ -196,6 +218,8 @@
((uint8_t*) (addr))[1] = (uint8_t) (((uint32_t) (value32)) >> 16); \
((uint8_t*) (addr))[0] = (uint8_t) (((uint32_t) (value32)) >> 24); \
} while (0)
+/* Indicate that _MHD_PUT_32BIT_BE does not need aligned pointer */
+#define _MHD_PUT_32BIT_BE_UNALIGNED 1
#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
/* _MHD_GET_32BIT_BE (addr)
@@ -215,6 +239,8 @@
| (((uint32_t) (((const uint8_t*) addr)[1])) << 16) \
| (((uint32_t) (((const uint8_t*) addr)[2])) << 8) \
| ((uint32_t) (((const uint8_t*) addr)[3])) )
+/* Indicate that _MHD_GET_32BIT_BE does not need aligned pointer */
+#define _MHD_GET_32BIT_BE_UNALIGNED 1
#endif /* _MHD_BYTE_ORDER != _MHD_LITTLE_ENDIAN */
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.