Implemented basement to work with unaligned data

This commit is contained in:
Evgeny Grin (Karlson2k)
2021-05-18 19:37:10 +03:00
parent 7676e698a9
commit 89387e53fe
4 changed files with 168 additions and 17 deletions
+50
View File
@@ -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]])
+8 -8
View File
@@ -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
+75
View File
@@ -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 */
+35 -9
View File
@@ -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 */