Skip to content

Commit fbea809

Browse files
committed
Do not rely on volatile for double/float decoding
I believe volatile was used to ensure that the compile does not optimize the code in ways that break the bit manipulation. Switching to memcpy and using the built-in bswap implementations when available seems like a better way to solve the issue. This also fixes the following warning: ``` /home/greg/MaxMind/MaxMindDBSwift/Sources/CLibMaxMindDB/libmaxminddb-1.12.2/src/maxminddb.c:1781:12: warning: passing 'volatile uint8_t *' (aka 'volatile unsigned char *') to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers] 1781 | memcpy(q, p, 4); | ^ /usr/include/string.h:43:39: note: passing argument to parameter '__dest' here 43 | extern void *memcpy (void *__restrict __dest, const void *__restrict __src, | ^ /home/greg/MaxMind/MaxMindDBSwift/Sources/CLibMaxMindDB/libmaxminddb-1.12.2/src/maxminddb.c:1799:12: warning: passing 'volatile uint8_t *' (aka 'volatile unsigned char *') to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers] 1799 | memcpy(q, p, 8); | ^ /usr/include/string.h:43:39: note: passing argument to parameter '__dest' here 43 | extern void *memcpy (void *__restrict __dest, const void *__restrict __src, | ^ 2 warnings generated. ```
1 parent 67ca8a5 commit fbea809

File tree

2 files changed

+52
-20
lines changed

2 files changed

+52
-20
lines changed

Changes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.13.0
2+
3+
* The handling of float and double types was rewritten to fix compiler errors
4+
and to eliminate the use of volatile.
5+
16
## 1.12.2 - 2025-01-10
27

38
* `MMDB_get_entry_data_list()` now always sets the passed `entry_data_list`

src/maxminddb.c

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,38 +1767,65 @@ static int get_entry_data_list(const MMDB_s *const mmdb,
17671767
return MMDB_SUCCESS;
17681768
}
17691769

1770+
#ifndef __has_builtin
1771+
#define __has_builtin(x) 0
1772+
#endif
1773+
1774+
static inline uint32_t bswap32(uint32_t x) {
1775+
#if defined(_MSC_VER)
1776+
return _byteswap_ulong(x);
1777+
#elif __has_builtin(__builtin_bswap32)
1778+
return __builtin_bswap32(x);
1779+
#else
1780+
x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0x00FF00FF);
1781+
return (x << 16) | (x >> 16);
1782+
#endif
1783+
}
1784+
1785+
static inline uint64_t bswap64(uint64_t x) {
1786+
#if defined(_MSC_VER)
1787+
return _byteswap_uint64(x);
1788+
#elif __has_builtin(__builtin_bswap64)
1789+
return __builtin_bswap64(x);
1790+
#else
1791+
x = ((x & 0x00000000FFFFFFFFULL) << 32) |
1792+
((x & 0xFFFFFFFF00000000ULL) >> 32);
1793+
x = ((x & 0x0000FFFF0000FFFFULL) << 16) |
1794+
((x & 0xFFFF0000FFFF0000ULL) >> 16);
1795+
return ((x & 0x00FF00FF00FF00FFULL) << 8) |
1796+
((x & 0xFF00FF00FF00FF00ULL) >> 8);
1797+
#endif
1798+
}
1799+
17701800
static float get_ieee754_float(const uint8_t *restrict p) {
1771-
volatile float f;
1772-
volatile uint8_t *q = (volatile void *)&f;
1801+
float f;
1802+
uint32_t i;
1803+
1804+
memcpy(&i, p, sizeof(uint32_t));
1805+
17731806
/* Windows builds don't use autoconf but we can assume they're all
17741807
* little-endian. */
17751808
#if MMDB_LITTLE_ENDIAN || _WIN32
1776-
q[3] = p[0];
1777-
q[2] = p[1];
1778-
q[1] = p[2];
1779-
q[0] = p[3];
1780-
#else
1781-
memcpy(q, p, 4);
1809+
i = bswap32(i);
17821810
#endif
1811+
1812+
memcpy(&f, &i, sizeof(float));
1813+
17831814
return f;
17841815
}
17851816

17861817
static double get_ieee754_double(const uint8_t *restrict p) {
1787-
volatile double d;
1788-
volatile uint8_t *q = (volatile void *)&d;
1818+
double d;
1819+
uint64_t i;
1820+
1821+
memcpy(&i, p, sizeof(uint64_t));
1822+
17891823
#if MMDB_LITTLE_ENDIAN || _WIN32
1790-
q[7] = p[0];
1791-
q[6] = p[1];
1792-
q[5] = p[2];
1793-
q[4] = p[3];
1794-
q[3] = p[4];
1795-
q[2] = p[5];
1796-
q[1] = p[6];
1797-
q[0] = p[7];
1798-
#else
1799-
memcpy(q, p, 8);
1824+
i = bswap64(i);
18001825
#endif
18011826

1827+
memcpy(&d, &i, sizeof(double));
1828+
18021829
return d;
18031830
}
18041831

0 commit comments

Comments
 (0)