Skip to content

Commit 5a627c5

Browse files
authored
Merge pull request #264 from gilles-peskine-arm/test_malloc_0_null
Test the library when malloc(0) returns NULL
2 parents 0a048b2 + 31b0a3c commit 5a627c5

File tree

3 files changed

+137
-0
lines changed

3 files changed

+137
-0
lines changed

programs/test/selftest.c

Lines changed: 83 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,86 @@
7779
#endif
7880

7981

82+
#if defined MBEDTLS_SELF_TEST
83+
/* Sanity check for malloc. This is not expected to fail, and is rather
84+
* intended to display potentially useful information about the platform,
85+
* in particular the behavior of malloc(0). */
86+
static int calloc_self_test( int verbose )
87+
{
88+
int failures = 0;
89+
void *empty1 = mbedtls_calloc( 0, 1 );
90+
void *empty2 = mbedtls_calloc( 0, 1 );
91+
void *buffer1 = mbedtls_calloc( 1, 1 );
92+
void *buffer2 = mbedtls_calloc( 1, 1 );
93+
uintptr_t old_buffer1;
94+
95+
if( empty1 == NULL && empty2 == NULL )
96+
{
97+
if( verbose )
98+
mbedtls_printf( " CALLOC(0): passed (NULL)\n" );
99+
}
100+
else if( empty1 == NULL || empty2 == NULL )
101+
{
102+
if( verbose )
103+
mbedtls_printf( " CALLOC(0): failed (mix of NULL and non-NULL)\n" );
104+
++failures;
105+
}
106+
else if( empty1 == empty2 )
107+
{
108+
if( verbose )
109+
mbedtls_printf( " CALLOC(0): passed (same non-null)\n" );
110+
}
111+
else
112+
{
113+
if( verbose )
114+
mbedtls_printf( " CALLOC(0): passed (distinct non-null)\n" );
115+
}
116+
117+
if( buffer1 == NULL || buffer2 == NULL )
118+
{
119+
if( verbose )
120+
mbedtls_printf( " CALLOC(1): failed (NULL)\n" );
121+
++failures;
122+
}
123+
else if( buffer1 == buffer2 )
124+
{
125+
if( verbose )
126+
mbedtls_printf( " CALLOC(1): failed (same buffer twice)\n" );
127+
++failures;
128+
}
129+
else
130+
{
131+
if( verbose )
132+
mbedtls_printf( " CALLOC(1): passed\n" );
133+
}
134+
135+
old_buffer1 = (uintptr_t) buffer1;
136+
mbedtls_free( buffer1 );
137+
buffer1 = mbedtls_calloc( 1, 1 );
138+
if( buffer1 == NULL )
139+
{
140+
if( verbose )
141+
mbedtls_printf( " CALLOC(1 again): failed (NULL)\n" );
142+
++failures;
143+
}
144+
else
145+
{
146+
if( verbose )
147+
mbedtls_printf( " CALLOC(1 again): passed (%s address)\n",
148+
(uintptr_t) old_buffer1 == (uintptr_t) buffer1 ?
149+
"same" : "different" );
150+
}
151+
152+
if( verbose )
153+
mbedtls_printf( "\n" );
154+
mbedtls_free( empty1 );
155+
mbedtls_free( empty2 );
156+
mbedtls_free( buffer1 );
157+
mbedtls_free( buffer2 );
158+
return( failures );
159+
}
160+
#endif /* MBEDTLS_SELF_TEST */
161+
80162
static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret )
81163
{
82164
int ret;
@@ -173,6 +255,7 @@ typedef struct
173255

174256
const selftest_t selftests[] =
175257
{
258+
{"calloc", calloc_self_test},
176259
#if defined(MBEDTLS_MD2_C)
177260
{"md2", mbedtls_md2_self_test},
178261
#endif
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/* config.h wrapper that forces calloc(0) to return NULL.
2+
* Used for testing.
3+
*/
4+
/*
5+
* Copyright (C) 2019, ARM Limited, All Rights Reserved
6+
* SPDX-License-Identifier: Apache-2.0
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
9+
* not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*
20+
* This file is part of mbed TLS (https://tls.mbed.org)
21+
*/
22+
23+
#ifndef MBEDTLS_CONFIG_H
24+
/* Don't #define MBEDTLS_CONFIG_H, let config.h do it. */
25+
26+
#include "mbedtls/config.h"
27+
28+
#include <stdlib.h>
29+
static inline void *custom_calloc( size_t nmemb, size_t size )
30+
{
31+
if( nmemb == 0 || size == 0 )
32+
return( NULL );
33+
return( calloc( nmemb, size ) );
34+
}
35+
36+
#define MBEDTLS_PLATFORM_MEMORY
37+
#define MBEDTLS_PLATFORM_STD_CALLOC custom_calloc
38+
39+
#endif /* MBEDTLS_CONFIG_H */

tests/scripts/all.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,21 @@ component_test_platform_calloc_macro () {
822822
make test
823823
}
824824

825+
component_test_malloc_0_null () {
826+
msg "build: malloc(0) returns NULL (ASan+UBSan build)"
827+
scripts/config.pl full
828+
scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
829+
make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined'
830+
831+
msg "test: malloc(0) returns NULL (ASan+UBSan build)"
832+
make test
833+
834+
msg "selftest: malloc(0) returns NULL (ASan+UBSan build)"
835+
# Just the calloc selftest. "make test" ran the others as part of the
836+
# test suites.
837+
if_build_succeeded programs/test/selftest calloc
838+
}
839+
825840
component_test_aes_fewer_tables () {
826841
msg "build: default config with AES_FEWER_TABLES enabled"
827842
scripts/config.pl set MBEDTLS_AES_FEWER_TABLES

0 commit comments

Comments
 (0)