Skip to content

Commit 1fd94fa

Browse files
Add a calloc self-test
Add a very basic test of calloc to the selftest program. The selftest program acts in its capacity as a platform compatibility checker rather than in its capacity as a test of the library. The main objective is to report whether calloc returns NULL for a size of 0. Also observe whether a free/alloc sequence returns the address that was just freed and whether a size overflow is properly detected.
1 parent 3f20efc commit 1fd94fa

File tree

1 file changed

+100
-0
lines changed

1 file changed

+100
-0
lines changed

programs/test/selftest.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
#else
6666
#include <stdio.h>
6767
#include <stdlib.h>
68+
#define mbedtls_calloc calloc
69+
#define mbedtls_free free
6870
#define mbedtls_printf printf
6971
#define mbedtls_snprintf snprintf
7072
#define mbedtls_exit exit
@@ -77,6 +79,103 @@
7779
#endif
7880

7981

82+
/* Sanity check for malloc. This is not expected to fail, and is rather
83+
* intended to display potentially useful information about the platform,
84+
* in particular the behavior of malloc(0). */
85+
static int calloc_self_test( int verbose )
86+
{
87+
int failures = 0;
88+
void *empty1 = mbedtls_calloc( 0, 1 );
89+
void *empty2 = mbedtls_calloc( 0, 1 );
90+
void *buffer1 = mbedtls_calloc( 1, 1 );
91+
void *buffer2 = mbedtls_calloc( 1, 1 );
92+
/* Attempt to allocate a size that's larger than size_t. This
93+
* should fail. With AddressSanitizer, this crashes the program by
94+
* default; to avoid this, set the environment variable
95+
* ASAN_OPTIONS=allocator_may_return_null=1 when running this program.
96+
*/
97+
void *overflow = mbedtls_calloc( SIZE_MAX / 2 + 1, 2 );
98+
uintptr_t old_buffer1;
99+
100+
if( empty1 == NULL && empty2 == NULL )
101+
{
102+
if( verbose )
103+
mbedtls_printf( " CALLOC(0): passed (NULL)\n" );
104+
}
105+
else if( empty1 == NULL || empty2 == NULL )
106+
{
107+
if( verbose )
108+
mbedtls_printf( " CALLOC(0): failed (mix of NULL and non-NULL)\n" );
109+
++failures;
110+
}
111+
else if( empty1 == empty2 )
112+
{
113+
if( verbose )
114+
mbedtls_printf( " CALLOC(0): passed (same non-null)\n" );
115+
}
116+
else
117+
{
118+
if( verbose )
119+
mbedtls_printf( " CALLOC(0): passed (distinct non-null)\n" );
120+
}
121+
122+
if( buffer1 == NULL || buffer2 == NULL )
123+
{
124+
if( verbose )
125+
mbedtls_printf( " CALLOC(1): failed (NULL)\n" );
126+
++failures;
127+
}
128+
else if( buffer1 == buffer2 )
129+
{
130+
if( verbose )
131+
mbedtls_printf( " CALLOC(1): failed (same buffer twice)\n" );
132+
++failures;
133+
}
134+
else
135+
{
136+
if( verbose )
137+
mbedtls_printf( " CALLOC(1): passed\n" );
138+
}
139+
140+
old_buffer1 = (uintptr_t) buffer1;
141+
mbedtls_free( buffer1 );
142+
buffer1 = mbedtls_calloc( 1, 1 );
143+
if( buffer1 == NULL )
144+
{
145+
if( verbose )
146+
mbedtls_printf( " CALLOC(1 again): failed (NULL)\n" );
147+
++failures;
148+
}
149+
else
150+
{
151+
if( verbose )
152+
mbedtls_printf( " CALLOC(1 again): passed (%s address)\n",
153+
(uintptr_t) old_buffer1 == (uintptr_t) buffer1 ?
154+
"same" : "different" );
155+
}
156+
157+
if( overflow == NULL )
158+
{
159+
if( verbose )
160+
mbedtls_printf( " CALLOC(overflow): passed\n" );
161+
}
162+
else
163+
{
164+
if( verbose )
165+
mbedtls_printf( " CALLOC(overflow): failed\n" );
166+
++failures;
167+
}
168+
169+
if( verbose )
170+
mbedtls_printf( "\n" );
171+
mbedtls_free( empty1 );
172+
mbedtls_free( empty2 );
173+
mbedtls_free( buffer1 );
174+
mbedtls_free( buffer2 );
175+
mbedtls_free( overflow );
176+
return( failures );
177+
}
178+
80179
static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
81180
{
82181
int ret;
@@ -173,6 +272,7 @@ typedef struct
173272

174273
const selftest_t selftests[] =
175274
{
275+
{"calloc", calloc_self_test},
176276
#if defined(MBEDTLS_MD2_C)
177277
{"md2", mbedtls_md2_self_test},
178278
#endif

0 commit comments

Comments
 (0)