mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-03-28 15:11:06 +01:00
MinGW uses a legacy printf by default which doesn't support the `z` modifier for `size_t`. Skip these test cases on MinGW. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
141 lines
4.1 KiB
C
141 lines
4.1 KiB
C
/* BEGIN_HEADER */
|
|
|
|
/* The printf test functions take a format argument from the test data
|
|
* for several reasons:
|
|
* - For some tests, it makes sense to vary the format.
|
|
* - For all tests, it means we're testing the actual printf function
|
|
* that parses the format at runtime, and not a compiler optimization.
|
|
* (It may be useful to add tests that allow compiler optimizations.
|
|
* There aren't any yet at the time of writing.)
|
|
*/
|
|
|
|
#include "mbedtls/platform.h"
|
|
|
|
#include <stdio.h>
|
|
#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 '"'
|
|
#define COLON_CHAR ':'
|
|
#define QUESTION_CHAR '?'
|
|
#define BACKSLASH_CHAR '\\'
|
|
#define LOWERCASE_N_CHAR 'n'
|
|
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_CASE */
|
|
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);
|
|
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;
|
|
|
|
exit:
|
|
mbedtls_free(output);
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void printf_long_max(const char *format, /* "%lx" or longer type */
|
|
long value)
|
|
{
|
|
char *expected = NULL;
|
|
char *output = NULL;
|
|
/* 2 hex digits per byte */
|
|
const size_t n = sizeof(value) * 2;
|
|
|
|
/* We assume that long has no padding bits! */
|
|
TEST_CALLOC(expected, n + 1);
|
|
expected[0] = '7';
|
|
memset(expected + 1, 'f', sizeof(value) * 2 - 1);
|
|
|
|
TEST_CALLOC(output, n + 1);
|
|
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, value));
|
|
TEST_MEMORY_COMPARE(expected, n + 1, output, n + 1);
|
|
mbedtls_free(output);
|
|
output = NULL;
|
|
|
|
exit:
|
|
mbedtls_free(output);
|
|
mbedtls_free(expected);
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void printf_char2(char *format, /* "%c%c" */
|
|
int arg1, int arg2, char *result)
|
|
{
|
|
char *output = NULL;
|
|
const size_t n = strlen(result);
|
|
|
|
/* Nominal case: buffer just large enough */
|
|
TEST_CALLOC(output, n + 1);
|
|
TEST_EQUAL(n, mbedtls_snprintf(output, n + 1, format, arg1, arg2));
|
|
TEST_MEMORY_COMPARE(result, n + 1, output, n + 1);
|
|
mbedtls_free(output);
|
|
output = NULL;
|
|
|
|
exit:
|
|
mbedtls_free(output);
|
|
}
|
|
/* END_CASE */
|