Merge pull request #10621 from gilles-peskine-arm/unix-detection-202601-3.6

Backport 3.6: Simplify platform requirements
This commit is contained in:
Gilles Peskine
2026-03-06 18:06:04 +00:00
committed by GitHub
19 changed files with 262 additions and 47 deletions

6
ChangeLog.d/unistd.txt Normal file
View File

@@ -0,0 +1,6 @@
Changes
* Tweak the detection of Unix-like platforms, which makes more system
interfaces (timing, threading) available on Haiku, QNX and Midipix.
Bugfix
* Fix a build failure with dietlibc.

View File

@@ -27,6 +27,24 @@
#define MBEDTLS_HAVE_NEON_INTRINSICS
#endif
/* Decide whether we're built for a Unix-like platform.
*/
#if defined(MBEDTLS_TEST_PLATFORM_IS_NOT_UNIXLIKE) //no-check-names
/* We may be building on a Unix-like platform, but for test purposes,
* do not try to use Unix features. */
#elif defined(_WIN32)
/* If Windows platform interfaces are available, we use them, even if
* a Unix-like might also to be available. */
/* defined(_WIN32) ==> we can include <windows.h> */
#elif defined(unix) || defined(__unix) || defined(__unix__) || \
(defined(__APPLE__) && defined(__MACH__)) || \
defined(__HAIKU__) || \
defined(__midipix__) || \
/* Add other Unix-like platform indicators here ^^^^ */ 0
/* defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) ==> we can include <unistd.h> */
#define MBEDTLS_PLATFORM_IS_UNIXLIKE
#endif
/** Helper to define a function as static except when building invasive tests.
*
* If a function is only used inside its own source file and should be

View File

@@ -21,6 +21,16 @@
/* DEBUG_BUF_SIZE must be at least 2 */
#define DEBUG_BUF_SIZE 512
int mbedtls_debug_snprintf(char *dest, size_t maxlen,
const char *format, ...)
{
va_list argp;
va_start(argp, format);
int ret = mbedtls_vsnprintf(dest, maxlen, format, argp);
va_end(argp);
return ret;
}
static int debug_threshold = 0;
void mbedtls_debug_set_threshold(int threshold)

View File

@@ -12,6 +12,19 @@
#include "mbedtls/debug.h"
/* This should be equivalent to mbedtls_snprintf(). But it might not be due
* to platform shenanigans. For example, Mbed TLS and TF-PSA-Crypto could
* have inconsistent platform definitions. On Mingw, some code might
* be built with a different setting of __USE_MINGW_ANSI_STDIO, resulting
* in an old non-C99 printf being used somewhere.
*
* Our library assumes that mbedtls_snprintf() and other printf functions
* are consistent throughout. This function is not an official API and
* is not meant to be used inside the library. It is provided to help
* debugging printf inconsistencies issues. If you need it, good luck!
*/
int mbedtls_debug_snprintf(char *dest, size_t maxlen,
const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(3, 4);
/**
* \brief Print a message to the debug output. This function is always used
* through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl

View File

@@ -19,9 +19,7 @@
#if defined(MBEDTLS_NET_C)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__) && !defined(__midipix__)
#if !defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) && !defined(_WIN32)
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h"
#endif

View File

@@ -147,12 +147,9 @@ void mbedtls_zeroize_and_free(void *buf, size_t len)
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
#include <time.h>
#if !defined(_WIN32) && (defined(unix) || \
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
defined(__MACH__)) || defined(__midipix__))
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#include <unistd.h>
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
* (__APPLE__ && __MACH__) || __midipix__) */
#endif
#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \
(defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \
@@ -218,12 +215,10 @@ void (*mbedtls_test_hook_test_fail)(const char *, int, const char *);
#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT)
#include <time.h>
#if !defined(_WIN32) && \
(defined(unix) || defined(__unix) || defined(__unix__) || \
(defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#include <unistd.h>
#endif \
/* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */
#endif
#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__)
mbedtls_ms_time_t mbedtls_ms_time(void)
{

View File

@@ -21,9 +21,7 @@
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
#if !defined(_WIN32) && (defined(unix) || \
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
defined(__MACH__)))
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#include <unistd.h>
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
* (__APPLE__ && __MACH__)) */

View File

@@ -13,9 +13,7 @@
#if !defined(MBEDTLS_TIMING_ALT)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__) && !defined(__midipix__)
#if !defined(_WIN32) && !defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h"
#endif

View File

@@ -882,7 +882,7 @@ component_test_crypto_for_psa_service () {
component_build_crypto_baremetal () {
msg "build: make, crypto only, baremetal config"
scripts/config.py crypto_baremetal
make CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/"
make CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/ -DMBEDTLS_TEST_PLATFORM_IS_NOT_UNIXLIKE"
are_empty_libraries library/libmbedx509.* library/libmbedtls.*
}

View File

@@ -222,7 +222,7 @@ component_test_full_deprecated_warning () {
component_build_baremetal () {
msg "build: make, baremetal config"
scripts/config.py baremetal
make CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/"
make CFLAGS="-O1 -Werror -I$PWD/framework/tests/include/baremetal-override/ -DMBEDTLS_TEST_PLATFORM_IS_NOT_UNIXLIKE"
}
support_build_baremetal () {

View File

@@ -275,7 +275,12 @@ static int convert_params(size_t cnt, char **params,
* \return 0 for success else 1
*/
#if defined(__GNUC__)
# if defined(__dietlibc__)
/* __noinline__ is a macro in dietlibc... */
__attribute__((noinline))
# else
__attribute__((__noinline__))
# endif
#endif
static int test_snprintf(size_t n, const char *ref_buf, int ref_ret)
{

View File

@@ -23,6 +23,17 @@
#endif
#endif
#if defined(__FreeBSD__)
/* On FreeBSD as of 14.3, no value of _POSIX_C_SOURCE is enough for
* gettimeofday(), you need _XOPEN_SOURCE (any value).
* Furthermore, setting _XOPEN_SOURCE to 500 removes support for long long
* in libc, so you need at least 600 for e.g. strtoull().
*/
#if !defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE 600
#endif
#endif
#include "mbedtls/build_info.h"
/* Test code may use deprecated identifiers only if the preprocessor symbol

View File

@@ -113,11 +113,11 @@ void printf_int_expr(int format_indicator, intmax_t sizeof_x, intmax_t x, char *
/* Nominal case: buffer just large enough */
TEST_CALLOC(output, n + 1);
if ((size_t) sizeof_x <= sizeof(int)) { // Any smaller integers would be promoted to an int due to calling a vararg function
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (int) x));
TEST_EQUAL(n, mbedtls_debug_snprintf(output, n + 1, format, (int) x));
} else if (sizeof_x == sizeof(long)) {
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long) x));
TEST_EQUAL(n, mbedtls_debug_snprintf(output, n + 1, format, (long) x));
} else if (sizeof_x == sizeof(long long)) {
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, (long long) x));
TEST_EQUAL(n, mbedtls_debug_snprintf(output, n + 1, format, (long long) x));
} else {
TEST_FAIL(
"sizeof_x <= sizeof(int) || sizeof_x == sizeof(long) || sizeof_x == sizeof(long long)");

View File

@@ -127,7 +127,7 @@ void check_mbedtls_calloc_overallocation(intmax_t num, intmax_t size)
unsigned char *buf;
buf = mbedtls_calloc((size_t) num, (size_t) size);
/* Dummy usage of the pointer to prevent optimizing it */
mbedtls_printf("calloc pointer : %p\n", buf);
mbedtls_printf("calloc pointer : %p\n", (void *) buf);
TEST_ASSERT(buf == NULL);
exit:

View File

@@ -3,58 +3,86 @@
# and strings through the test framework.
printf "%d", 0
printf_int:"%d":0:"0"
printf_integer:"%d":PRINTF_CAST_INT:0:"0"
printf "%d", -0
printf_int:"%d":-0:"0"
printf_integer:"%d":PRINTF_CAST_INT:-0:"0"
printf "%d", 0x0
printf_int:"%d":0x0:"0"
printf_integer:"%d":PRINTF_CAST_INT:0x0:"0"
printf "%d", 0x00
printf_int:"%d":0x00:"0"
printf_integer:"%d":PRINTF_CAST_INT:0x00:"0"
printf "%d", 0x000000000000000000000000000000000000000000
printf_int:"%d":0x000000000000000000000000000000000000000000:"0"
printf_integer:"%d":PRINTF_CAST_INT:0x000000000000000000000000000000000000000000:"0"
printf "%d", -0x0
printf_int:"%d":-0x0:"0"
printf_integer:"%d":PRINTF_CAST_INT:-0x0:"0"
printf "%d", 1
printf_int:"%d":1:"1"
printf_integer:"%d":PRINTF_CAST_INT:1:"1"
printf "%d", 0x1
printf_int:"%d":0x1:"1"
printf_integer:"%d":PRINTF_CAST_INT:0x1:"1"
printf "%d", 0x0000000000000000000000000000000000000000001
printf_int:"%d":0x0000000000000000000000000000000000000000001:"1"
printf_integer:"%d":PRINTF_CAST_INT:0x0000000000000000000000000000000000000000001:"1"
printf "%d", -1
printf_int:"%d":-1:"-1"
printf_integer:"%d":PRINTF_CAST_INT:-1:"-1"
printf "%d", -0x1
printf_int:"%d":-0x1:"-1"
printf_integer:"%d":PRINTF_CAST_INT:-0x1:"-1"
printf "%d", -0x0000000000000000000000000000000000000000001
printf_int:"%d":-0x0000000000000000000000000000000000000000001:"-1"
printf_integer:"%d":PRINTF_CAST_INT:-0x0000000000000000000000000000000000000000001:"-1"
printf "%d", 2147483647
printf_int:"%d":2147483647:"2147483647"
printf_integer:"%d":PRINTF_CAST_INT:2147483647:"2147483647"
printf "%d", 0x7fffffff
printf_int:"%d":0x7fffffff:"2147483647"
printf_integer:"%d":PRINTF_CAST_INT:0x7fffffff:"2147483647"
printf "%d", -2147483647
printf_int:"%d":-2147483647:"-2147483647"
printf_integer:"%d":PRINTF_CAST_INT:-2147483647:"-2147483647"
printf "%d", -0x7fffffff
printf_int:"%d":-0x7fffffff:"-2147483647"
printf_integer:"%d":PRINTF_CAST_INT:-0x7fffffff:"-2147483647"
printf "%d", -2147483648
printf_int:"%d":-2147483648:"-2147483648"
printf_integer:"%d":PRINTF_CAST_INT:-2147483648:"-2147483648"
printf "%d", -0x80000000
printf_int:"%d":-0x80000000:"-2147483648"
printf_integer:"%d":PRINTF_CAST_INT:-0x80000000:"-2147483648"
printf "%u", 0x80000000
printf_integer:"%u":PRINTF_CAST_INT:-0x80000000:"2147483648"
printf "%zx", 0x12345678
depends_on:HAVE_C99_PRINTF
printf_integer:"%zx":PRINTF_CAST_SIZE_T:0x12345678:"12345678"
printf "%zu", 0x80000000
depends_on:HAVE_C99_PRINTF
printf_integer:"%zu":PRINTF_CAST_SIZE_T:0x80000000:"2147483648"
printf "%zx", 0xffffffff
depends_on:HAVE_C99_PRINTF
printf_integer:"%zx":PRINTF_CAST_SIZE_T:0xffffffff:"ffffffff"
printf "%zx", 0xffffffffffffffff
depends_on:HAVE_C99_PRINTF:SIZE_T_AT_LEAST_64_BIT
printf_integer:"%zx":PRINTF_CAST_SIZE_T:0xffffffffffffffff:"ffffffffffffffff"
printf "%lld", 0x7fffffffffffffff
printf_integer:"%lld":PRINTF_CAST_LONG_LONG:0x7fffffffffffffff:"9223372036854775807"
printf "%lld", -0x8000000000000000
printf_integer:"%lld":PRINTF_CAST_LONG_LONG:-0x8000000000000000:"-9223372036854775808"
printf "%llx", 0x102030405060708
printf_integer:"%llx":PRINTF_CAST_UNSIGNED_LONG_LONG:0x0102030405060708:"102030405060708"
# Test that LONG_MAX is coming out untruncated through the test framework.
printf "%lx", LONG_MAX

View File

@@ -15,6 +15,34 @@
#include <stdlib.h>
#include <string.h>
#if SIZE_MAX >= 0xffffffffffffffff
#define SIZE_T_AT_LEAST_64_BIT
#endif
/* Older Windows runtimes have a non-compliant printf family, e.g.
* it doesn't understand `%zu` to print a `size_t`. MSVC provides a
* C99-compliant printf family (at least enough for our purposes),
* since Visual Studio 2015. With MinGW, you get the non-compliant legacy
* printf by default, but can select the standard-compliant version
* at compile time. In the Mbed TLS 3.6 LTS, we use the default, so
* we can't rely on %z being understood. The debug module defines
* `MBEDTLS_PRINTF_SIZET` for that, and this is tested in test_suite_debug.
* Here we just skip the test cases that break the legacy Windows printf.
*/
#if !(defined(__MINGW32__))
#define HAVE_C99_PRINTF
#endif
typedef enum {
PRINTF_CAST_INT,
PRINTF_CAST_UNSIGNED,
PRINTF_CAST_SIZE_T,
PRINTF_CAST_LONG,
PRINTF_CAST_UNSIGNED_LONG,
PRINTF_CAST_LONG_LONG,
PRINTF_CAST_UNSIGNED_LONG_LONG,
} printf_cast_type_t;
#define NEWLINE_CHAR '\n'
#define SPACE_CHAR ' '
#define DOUBLE_QUOTE_CHAR '"'
@@ -22,18 +50,41 @@
#define QUESTION_CHAR '?'
#define BACKSLASH_CHAR '\\'
#define LOWERCASE_N_CHAR 'n'
/* END_HEADER */
/* BEGIN_CASE */
void printf_int(char *format, /* any format expecting one int argument, e.g. "%d" */
int x, char *result)
void printf_integer(char *format, /* format expecting one foo_t argument */
int type, /* enum value from printf_cast_type_t */
intmax_t value,
char *result)
{
char *output = NULL;
const size_t n = strlen(result);
int ret = 0;
/* Nominal case: buffer just large enough */
TEST_CALLOC(output, n + 1);
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, x));
switch (type) {
case PRINTF_CAST_INT:
ret = mbedtls_snprintf(output, n + 1, format, (int) value);
break;
case PRINTF_CAST_UNSIGNED:
ret = mbedtls_snprintf(output, n + 1, format, (unsigned) value);
break;
case PRINTF_CAST_SIZE_T:
ret = mbedtls_snprintf(output, n + 1, format, (size_t) value);
break;
case PRINTF_CAST_LONG_LONG:
ret = mbedtls_snprintf(output, n + 1, format, (long long) value);
break;
case PRINTF_CAST_UNSIGNED_LONG_LONG:
ret = mbedtls_snprintf(output, n + 1, format, (unsigned long long) value);
break;
default:
TEST_FAIL("Unsupported type");
}
TEST_EQUAL(n, ret);
TEST_MEMORY_COMPARE(result, n + 1, output, n + 1);
mbedtls_free(output);
output = NULL;

View File

@@ -0,0 +1,16 @@
<unistd.h> smoke test
unistd_available:
# At the time of writing, we don't actually use CLOCK_REALTIME.
# But it's the only clock that's guaranteed by POSIX.
clock_gettime(CLOCK_REALTIME) smoke test
clock_gettime_available:CLOCK_REALTIME
# Used for mbedtls_ms_time() on platforms where we don't think
# CLOCK_BOOTTIME is available.
clock_gettime(CLOCK_MONOTONIC) smoke test
clock_gettime_available:CLOCK_MONOTONIC
# Used in library/timing.c and programs/test/benchmark.c
gettimeofday() smoke test
gettimeofday_available:

View File

@@ -0,0 +1,68 @@
/* BEGIN_HEADER */
/* Test access to the Unix primitives used in platform_util.c and elsewhere.
* We aren't testing that they work, just getting an easy-to-understand
* diagnostic if they aren't available.
* (There is a separate test suite for the platform_util.h interfacces.)
*/
#include <mbedtls/platform_util.h>
#include <mbedtls/platform.h>
#include "common.h"
#if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#else /* defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) */
/* Constants used in the test data need to be defined even if no test
* functions that use them are enabled.
* Undefine the macros first in case a system header does define them
* even though we haven't recognized the platform as Unix-like. */
#undef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#undef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 0
#endif /* defined(MBEDTLS_PLATFORM_IS_UNIXLIKE) */
/* END_HEADER */
/* Note: we can't make the whole test suite depend on
* MBEDTLS_PLATFORM_IS_UNIXLIKE, because file-level dependencies can only
* come from build_info.h, platform.h or some test helper headers, not
* from internal macros. */
/* BEGIN_DEPENDENCIES
* END_DEPENDENCIES */
/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */
void unistd_available()
{
pid_t pid = getpid();
TEST_LE_S(1, pid);
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */
void clock_gettime_available(int clockid)
{
struct timespec ts = { 0, 0 };
memset(&ts, 0, sizeof(ts));
int ret = clock_gettime(clockid, &ts);
TEST_ASSERT_ERRNO(ret == 0);
TEST_ASSERT(ts.tv_sec != 0 || ts.tv_nsec != 0);
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PLATFORM_IS_UNIXLIKE */
void gettimeofday_available()
{
struct timeval tv = { 0, 0 };
memset(&tv, 0, sizeof(tv));
int ret = gettimeofday(&tv, NULL);
TEST_ASSERT_ERRNO(ret == 0);
TEST_LE_S(1, tv.tv_sec);
}
/* END_CASE */