19e7bcd65Smrg/*
2fdf6a26fSmrg * Copyright (c) 2011, 2023, Oracle and/or its affiliates.
39e7bcd65Smrg *
49e7bcd65Smrg * Permission is hereby granted, free of charge, to any person obtaining a
59e7bcd65Smrg * copy of this software and associated documentation files (the "Software"),
69e7bcd65Smrg * to deal in the Software without restriction, including without limitation
79e7bcd65Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
89e7bcd65Smrg * and/or sell copies of the Software, and to permit persons to whom the
99e7bcd65Smrg * Software is furnished to do so, subject to the following conditions:
109e7bcd65Smrg *
119e7bcd65Smrg * The above copyright notice and this permission notice (including the next
129e7bcd65Smrg * paragraph) shall be included in all copies or substantial portions of the
139e7bcd65Smrg * Software.
149e7bcd65Smrg *
159e7bcd65Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
169e7bcd65Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
179e7bcd65Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
189e7bcd65Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
199e7bcd65Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
209e7bcd65Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
219e7bcd65Smrg * DEALINGS IN THE SOFTWARE.
229e7bcd65Smrg */
239e7bcd65Smrg
24fdf6a26fSmrg#ifdef HAVE_CONFIG_H
25fdf6a26fSmrg#include <config.h>
26fdf6a26fSmrg#endif
27fdf6a26fSmrg
28fdf6a26fSmrg#include <X11/Xfuncproto.h>
299e7bcd65Smrg#include <X11/Intrinsic.h>
30fdf6a26fSmrg#include <X11/IntrinsicI.h>
319e7bcd65Smrg#include <glib.h>
329e7bcd65Smrg#include <stdio.h>
33fdf6a26fSmrg#include <stdlib.h>
349e7bcd65Smrg#include <string.h>
35fdf6a26fSmrg#include <errno.h>
36fdf6a26fSmrg#include <limits.h>
37fdf6a26fSmrg#include <setjmp.h>
38fdf6a26fSmrg#include <sys/resource.h>
39fdf6a26fSmrg#ifdef HAVE_MALLOC_H
40fdf6a26fSmrg# include <malloc.h>
41fdf6a26fSmrg#endif
429e7bcd65Smrg
439e7bcd65Smrgstatic const char *program_name;
449e7bcd65Smrg
45fdf6a26fSmrg#ifndef g_assert_no_errno /* defined in glib 2.66 & later*/
46fdf6a26fSmrg#define g_assert_no_errno(expr) g_assert_cmpint((expr), >=, 0)
47fdf6a26fSmrg#endif
48fdf6a26fSmrg
49fdf6a26fSmrg/*
50fdf6a26fSmrg * Check that allocations point to properly aligned memory.
51fdf6a26fSmrg * For libXt, we consider that to be aligned to an 8-byte (64-bit) boundary.
52fdf6a26fSmrg */
53fdf6a26fSmrg#define EXPECTED_ALIGNMENT 8
54fdf6a26fSmrg
55fdf6a26fSmrg#define CHECK_ALIGNMENT(ptr) \
56fdf6a26fSmrg    g_assert_cmpint(((uintptr_t)ptr) % EXPECTED_ALIGNMENT, ==, 0)
57fdf6a26fSmrg
58fdf6a26fSmrg/* Check that allocations point to expected amounts of memory, as best we can. */
59fdf6a26fSmrg#ifdef HAVE_MALLOC_USABLE_SIZE
60fdf6a26fSmrg# define CHECK_SIZE(ptr, size) do {		\
61fdf6a26fSmrg    size_t ps = malloc_usable_size(ptr);	\
62fdf6a26fSmrg    g_assert_cmpint(ps, >=, (size));		\
63fdf6a26fSmrg} while (0)
64fdf6a26fSmrg#else
65fdf6a26fSmrg# define CHECK_SIZE(ptr, size) *(((char *)ptr) + ((size) - 1)) = 0
66fdf6a26fSmrg#endif
67fdf6a26fSmrg
68fdf6a26fSmrg/* Limit we set for memory allocation to be able to test failure cases */
69fdf6a26fSmrg#define ALLOC_LIMIT (INT_MAX / 4)
70fdf6a26fSmrg
71fdf6a26fSmrg/* Square root of SIZE_MAX+1 */
72fdf6a26fSmrg#define SQRT_SIZE_MAX ((size_t)1 << (sizeof (size_t) * 4))
73fdf6a26fSmrg
749e7bcd65Smrg/* Just a long string of characters to pull from */
759e7bcd65Smrgconst char test_chars[] =
769e7bcd65Smrg    "|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel|"
779e7bcd65Smrg    "|010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si |"
789e7bcd65Smrg    "|020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb|"
799e7bcd65Smrg    "|030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us |"
809e7bcd65Smrg    "|040 sp |041  ! |042  \" |043  # |044  $ |045  % |046  & |047  ' |"
819e7bcd65Smrg    "|050  ( |051  ) |052  * |053  + |054  , |055  - |056  . |057  / |"
829e7bcd65Smrg    "|060  0 |061  1 |062  2 |063  3 |064  4 |065  5 |066  6 |067  7 |"
839e7bcd65Smrg    "|070  8 |071  9 |072  : |073  ; |074  < |075  = |076  > |077  ? |"
849e7bcd65Smrg    "|100  @ |101  A |102  B |103  C |104  D |105  E |106  F |107  G |"
859e7bcd65Smrg    "|110  H |111  I |112  J |113  K |114  L |115  M |116  N |117  O |"
869e7bcd65Smrg    "|120  P |121  Q |122  R |123  S |124  T |125  U |126  V |127  W |"
879e7bcd65Smrg    "|130  X |131  Y |132  Z |133  [ |134  \\ |135  ] |136  ^ |137  _ |"
889e7bcd65Smrg    "|140  ` |141  a |142  b |143  c |144  d |145  e |146  f |147  g |"
899e7bcd65Smrg    "|150  h |151  i |152  j |153  k |154  l |155  m |156  n |157  o |"
909e7bcd65Smrg    "|160  p |161  q |162  r |163  s |164  t |165  u |166  v |167  w |"
919e7bcd65Smrg    "|170  x |171  y |172  z |173  { |174  | |175  } |176  ~ |177 del|"
929e7bcd65Smrg    "| 00 nul| 01 soh| 02 stx| 03 etx| 04 eot| 05 enq| 06 ack| 07 bel|"
939e7bcd65Smrg    "| 08 bs | 09 ht | 0a nl | 0b vt | 0c np | 0d cr | 0e so | 0f si |"
949e7bcd65Smrg    "| 10 dle| 11 dc1| 12 dc2| 13 dc3| 14 dc4| 15 nak| 16 syn| 17 etb|"
959e7bcd65Smrg    "| 18 can| 19 em | 1a sub| 1b esc| 1c fs | 1d gs | 1e rs | 1f us |"
969e7bcd65Smrg    "| 20 sp | 21  ! | 22  \" | 23  # | 24  $ | 25  % | 26  & | 27  ' |"
979e7bcd65Smrg    "| 28  ( | 29  ) | 2a  * | 2b  + | 2c  , | 2d  - | 2e  . | 2f  / |"
989e7bcd65Smrg    "| 30  0 | 31  1 | 32  2 | 33  3 | 34  4 | 35  5 | 36  6 | 37  7 |"
999e7bcd65Smrg    "| 38  8 | 39  9 | 3a  : | 3b  ; | 3c  < | 3d  = | 3e  > | 3f  ? |"
1009e7bcd65Smrg    "| 40  @ | 41  A | 42  B | 43  C | 44  D | 45  E | 46  F | 47  G |"
1019e7bcd65Smrg    "| 48  H | 49  I | 4a  J | 4b  K | 4c  L | 4d  M | 4e  N | 4f  O |"
1029e7bcd65Smrg    "| 50  P | 51  Q | 52  R | 53  S | 54  T | 55  U | 56  V | 57  W |"
1039e7bcd65Smrg    "| 58  X | 59  Y | 5a  Z | 5b  [ | 5c  \\ | 5d  ] | 5e  ^ | 5f  _ |"
1049e7bcd65Smrg    "| 60  ` | 61  a | 62  b | 63  c | 64  d | 65  e | 66  f | 67  g |"
1059e7bcd65Smrg    "| 68  h | 69  i | 6a  j | 6b  k | 6c  l | 6d  m | 6e  n | 6f  o |"
1069e7bcd65Smrg    "| 70  p | 71  q | 72  r | 73  s | 74  t | 75  u | 76  v | 77  w |"
1079e7bcd65Smrg    "| 78  x | 79  y | 7a  z | 7b  { | 7c  | | 7d  } | 7e  ~ | 7f del|";
1089e7bcd65Smrg
1099e7bcd65Smrg
110fdf6a26fSmrg/* Environment saved by setjmp() */
111fdf6a26fSmrgstatic jmp_buf jmp_env;
112fdf6a26fSmrg
113fdf6a26fSmrgstatic void _X_NORETURN
114fdf6a26fSmrgxt_error_handler(String message)
115fdf6a26fSmrg{
116fdf6a26fSmrg    if (message && *message)
117fdf6a26fSmrg        fprintf(stderr, "Caught Error: %s\n", message);
118fdf6a26fSmrg    else
119fdf6a26fSmrg        fputs("Caught Error.\n", stderr);
120fdf6a26fSmrg
121fdf6a26fSmrg    /* Avoid exit() in XtErrorMsg() */
122fdf6a26fSmrg    longjmp(jmp_env, 1);
123fdf6a26fSmrg}
124fdf6a26fSmrg
125fdf6a26fSmrg
1269e7bcd65Smrg/* Test a simple short string & int */
1279e7bcd65Smrgstatic void test_XtAsprintf_short(void)
1289e7bcd65Smrg{
1299e7bcd65Smrg    char snbuf[1024];
1309e7bcd65Smrg    char *asbuf;
1319e7bcd65Smrg    gint32 r = g_test_rand_int();
1329e7bcd65Smrg    int snlen, aslen;
1339e7bcd65Smrg
1349e7bcd65Smrg    snlen = snprintf(snbuf, sizeof(snbuf), "%s: %d\n", program_name, r);
1359e7bcd65Smrg    aslen = XtAsprintf(&asbuf, "%s: %d\n", program_name, r);
1369e7bcd65Smrg
137fdf6a26fSmrg    g_assert_nonnull(asbuf);
138fdf6a26fSmrg    g_assert_cmpint(snlen, ==, aslen);
139fdf6a26fSmrg    g_assert_cmpstr(snbuf, ==, asbuf);
140fdf6a26fSmrg    g_assert_cmpint(asbuf[aslen], ==, '\0');
1419e7bcd65Smrg}
1429e7bcd65Smrg
1439e7bcd65Smrg/* Test a string long enough to be past the 256 character limit that
1449e7bcd65Smrg   makes XtAsprintf re-run snprintf after allocating memory */
1459e7bcd65Smrgstatic void test_XtAsprintf_long(void)
1469e7bcd65Smrg{
1479e7bcd65Smrg    char *asbuf;
1489e7bcd65Smrg    int aslen;
1499e7bcd65Smrg    gint r1 = g_test_rand_int_range(0, 256);
1509e7bcd65Smrg    gint r2 = g_test_rand_int_range(1024, sizeof(test_chars) - r1);
1519e7bcd65Smrg
1529e7bcd65Smrg    aslen = XtAsprintf(&asbuf, "%.*s", r2, test_chars + r1);
1539e7bcd65Smrg
154fdf6a26fSmrg    g_assert_nonnull(asbuf);
155fdf6a26fSmrg    g_assert_cmpint(aslen, ==, r2);
156fdf6a26fSmrg    g_assert_cmpint(strncmp(asbuf, test_chars + r1, r2), ==, 0);
157fdf6a26fSmrg    g_assert_cmpint(asbuf[aslen], ==, '\0');
158fdf6a26fSmrg}
159fdf6a26fSmrg
160fdf6a26fSmrg/* Make sure XtMalloc() works for a non-zero amount of memory */
161fdf6a26fSmrgstatic void test_XtMalloc_normal(void)
162fdf6a26fSmrg{
163fdf6a26fSmrg    void *p;
164fdf6a26fSmrg    /* Pick a size between 1 & 256K */
165fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (256 * 1024));
166fdf6a26fSmrg
167fdf6a26fSmrg    errno = 0;
168fdf6a26fSmrg
169fdf6a26fSmrg    p = XtMalloc(size);
170fdf6a26fSmrg    g_assert_nonnull(p);
171fdf6a26fSmrg    CHECK_ALIGNMENT(p);
172fdf6a26fSmrg    CHECK_SIZE(p, size);
173fdf6a26fSmrg
174fdf6a26fSmrg    /* make sure we can write to all the allocated memory */
175fdf6a26fSmrg    memset(p, 'A', size);
176fdf6a26fSmrg
177fdf6a26fSmrg    XtFree(p);
178fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
179fdf6a26fSmrg}
180fdf6a26fSmrg
181fdf6a26fSmrg/* Make sure XtMalloc(0) returns expected results */
182fdf6a26fSmrgstatic void test_XtMalloc_zero(void)
183fdf6a26fSmrg{
184fdf6a26fSmrg    void *p;
185fdf6a26fSmrg
186fdf6a26fSmrg    errno = 0;
187fdf6a26fSmrg
188fdf6a26fSmrg    p = XtMalloc(0);
189fdf6a26fSmrg#if !defined(MALLOC_0_RETURNS_NULL) || defined(XTMALLOC_BC)
190fdf6a26fSmrg    g_assert_nonnull(p);
191fdf6a26fSmrg#else
192fdf6a26fSmrg    g_assert_null(p);
193fdf6a26fSmrg#endif
194fdf6a26fSmrg    XtFree(p);
195fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
196fdf6a26fSmrg
197fdf6a26fSmrg    /* __XtMalloc always returns a non-NULL pointer for size == 0 */
198fdf6a26fSmrg    p = __XtMalloc(0);
199fdf6a26fSmrg    g_assert_nonnull(p);
200fdf6a26fSmrg    XtFree(p);
201fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
202fdf6a26fSmrg}
203fdf6a26fSmrg
204fdf6a26fSmrg/* Make sure sizes larger than the limit we set in main() fail */
205fdf6a26fSmrgstatic void test_XtMalloc_oversize(void)
206fdf6a26fSmrg{
207fdf6a26fSmrg    void *p;
208fdf6a26fSmrg
209fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
210fdf6a26fSmrg        p = XtMalloc(UINT_MAX - 1);
211fdf6a26fSmrg        g_assert_null(p);
212fdf6a26fSmrg    } else {
213fdf6a26fSmrg        /*
214fdf6a26fSmrg         * We jumped here from error handler as expected.
215fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
216fdf6a26fSmrg         * calls that override errno, when trying to load error message
217fdf6a26fSmrg         * files from different locations.
218fdf6a26fSmrg         */
219fdf6a26fSmrg    }
220fdf6a26fSmrg}
221fdf6a26fSmrg
222fdf6a26fSmrg/* Make sure XtMalloc catches integer overflow if possible, by requesting
223fdf6a26fSmrg * sizes that are so large that they cause overflows when either adding the
224fdf6a26fSmrg * malloc data block overhead or aligning.
225fdf6a26fSmrg *
226fdf6a26fSmrg * Testing integer overflow cases is limited by the fact that XtMalloc
227fdf6a26fSmrg * only takes unsigned arguments (typically 32-bit), and relies on
228fdf6a26fSmrg * the underlying libc malloc to catch overflow, which can't occur if
229fdf6a26fSmrg * 32-bit arguments are passed to a function taking 64-bit args.
230fdf6a26fSmrg */
231fdf6a26fSmrgstatic void test_XtMalloc_overflow(void)
232fdf6a26fSmrg{
233fdf6a26fSmrg#if UINT_MAX < SIZE_MAX
234fdf6a26fSmrg    g_test_skip("overflow not possible in this config");
235fdf6a26fSmrg#else
236fdf6a26fSmrg    void *p;
237fdf6a26fSmrg
238fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
239fdf6a26fSmrg        p = XtMalloc(SIZE_MAX);
240fdf6a26fSmrg        g_assert_null(p);
241fdf6a26fSmrg    } else {
242fdf6a26fSmrg        /*
243fdf6a26fSmrg         * We jumped here from error handler as expected.
244fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
245fdf6a26fSmrg         * calls that override errno, when trying to load error message
246fdf6a26fSmrg         * files from different locations.
247fdf6a26fSmrg         */
248fdf6a26fSmrg    }
249fdf6a26fSmrg
250fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
251fdf6a26fSmrg        p = XtMalloc(SIZE_MAX - 1);
252fdf6a26fSmrg        g_assert_null(p);
253fdf6a26fSmrg    } else {
254fdf6a26fSmrg        /*
255fdf6a26fSmrg         * We jumped here from error handler as expected.
256fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
257fdf6a26fSmrg         * calls that override errno, when trying to load error message
258fdf6a26fSmrg         * files from different locations.
259fdf6a26fSmrg         */
260fdf6a26fSmrg    }
261fdf6a26fSmrg
262fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
263fdf6a26fSmrg        p = XtMalloc(SIZE_MAX - 8);
264fdf6a26fSmrg        g_assert_null(p);
265fdf6a26fSmrg    } else {
266fdf6a26fSmrg        /*
267fdf6a26fSmrg         * We jumped here from error handler as expected.
268fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
269fdf6a26fSmrg         * calls that override errno, when trying to load error message
270fdf6a26fSmrg         * files from different locations.
271fdf6a26fSmrg         */
272fdf6a26fSmrg    }
273fdf6a26fSmrg#endif
274fdf6a26fSmrg}
275fdf6a26fSmrg
276fdf6a26fSmrg
277fdf6a26fSmrg
278fdf6a26fSmrg/* Make sure XtCalloc() works for a non-zero amount of memory */
279fdf6a26fSmrgstatic void test_XtCalloc_normal(void)
280fdf6a26fSmrg{
281fdf6a26fSmrg    char *p;
282fdf6a26fSmrg    /* Pick a number of elements between 1 & 16K */
283fdf6a26fSmrg    guint32 num = g_test_rand_int_range(1, (16 * 1024));
284fdf6a26fSmrg    /* Pick a size between 1 & 16K */
285fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (16 * 1024));
286fdf6a26fSmrg
287fdf6a26fSmrg    errno = 0;
288fdf6a26fSmrg
289fdf6a26fSmrg    p = XtCalloc(num, size);
290fdf6a26fSmrg    g_assert_nonnull(p);
291fdf6a26fSmrg    CHECK_ALIGNMENT(p);
292fdf6a26fSmrg    CHECK_SIZE(p, num * size);
293fdf6a26fSmrg
294fdf6a26fSmrg    /* make sure all the memory was zeroed */
295fdf6a26fSmrg    for (guint32 i = 0; i < (num * size); i++) {
296fdf6a26fSmrg        g_assert_cmpint(p[i], ==, 0);
297fdf6a26fSmrg    }
298fdf6a26fSmrg
299fdf6a26fSmrg    /* make sure we can write to all the allocated memory */
300fdf6a26fSmrg    memset(p, 'A', num * size);
301fdf6a26fSmrg
302fdf6a26fSmrg    XtFree(p);
303fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
304fdf6a26fSmrg}
305fdf6a26fSmrg
306fdf6a26fSmrg/* Make sure XtCalloc() returns the expected results for args of 0 */
307fdf6a26fSmrgstatic void test_XtCalloc_zero(void)
308fdf6a26fSmrg{
309fdf6a26fSmrg    void *p;
310fdf6a26fSmrg
311fdf6a26fSmrg    errno = 0;
312fdf6a26fSmrg
313fdf6a26fSmrg    p = XtCalloc(0, 0);
314fdf6a26fSmrg#if !defined(MALLOC_0_RETURNS_NULL) || defined(XTMALLOC_BC)
315fdf6a26fSmrg    g_assert_nonnull(p);
316fdf6a26fSmrg    XtFree(p);
317fdf6a26fSmrg#else
318fdf6a26fSmrg    g_assert_null(p);
319fdf6a26fSmrg#endif
320fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
321fdf6a26fSmrg
322fdf6a26fSmrg    p = XtCalloc(1, 0);
323fdf6a26fSmrg#if !defined(MALLOC_0_RETURNS_NULL) || defined(XTMALLOC_BC)
324fdf6a26fSmrg    g_assert_nonnull(p);
325fdf6a26fSmrg    XtFree(p);
326fdf6a26fSmrg#else
327fdf6a26fSmrg    g_assert_null(p);
328fdf6a26fSmrg#endif
329fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
330fdf6a26fSmrg
331fdf6a26fSmrg    p = XtCalloc(0, 1);
332fdf6a26fSmrg#if !defined(MALLOC_0_RETURNS_NULL)
333fdf6a26fSmrg    g_assert_nonnull(p);
334fdf6a26fSmrg    XtFree(p);
335fdf6a26fSmrg#else
336fdf6a26fSmrg    g_assert_null(p);
337fdf6a26fSmrg#endif
338fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
339fdf6a26fSmrg
340fdf6a26fSmrg    /* __XtCalloc always returns a non-NULL pointer for size == 0 */
341fdf6a26fSmrg    p = __XtCalloc(1, 0);
342fdf6a26fSmrg    g_assert_nonnull(p);
343fdf6a26fSmrg    XtFree(p);
344fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
345fdf6a26fSmrg}
346fdf6a26fSmrg
347fdf6a26fSmrg/* Make sure sizes larger than the limit we set in main() fail. */
348fdf6a26fSmrgstatic void test_XtCalloc_oversize(void)
349fdf6a26fSmrg{
350fdf6a26fSmrg    void *p;
351fdf6a26fSmrg
352fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
353fdf6a26fSmrg        p = XtCalloc(2, ALLOC_LIMIT);
354fdf6a26fSmrg        g_assert_null(p);
355fdf6a26fSmrg    } else {
356fdf6a26fSmrg        /*
357fdf6a26fSmrg         * We jumped here from error handler as expected.
358fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
359fdf6a26fSmrg         * calls that override errno, when trying to load error message
360fdf6a26fSmrg         * files from different locations.
361fdf6a26fSmrg         */
362fdf6a26fSmrg    }
363fdf6a26fSmrg}
364fdf6a26fSmrg
365fdf6a26fSmrg/* Make sure XtCalloc catches integer overflow if possible
366fdf6a26fSmrg *
367fdf6a26fSmrg * Testing integer overflow cases is limited by the fact that XtCalloc
368fdf6a26fSmrg * only takes unsigned arguments (typically 32-bit), and relies on
369fdf6a26fSmrg * the underlying libc calloc to catch overflow, which can't occur
370fdf6a26fSmrg * if 32-bit arguments are passed to a function taking 64-bit args.
371fdf6a26fSmrg */
372fdf6a26fSmrgstatic void test_XtCalloc_overflow(void)
373fdf6a26fSmrg{
374fdf6a26fSmrg#if UINT_MAX < SIZE_MAX
375fdf6a26fSmrg    g_test_skip("overflow not possible in this config");
376fdf6a26fSmrg#else
377fdf6a26fSmrg    void *p;
378fdf6a26fSmrg
379fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
380fdf6a26fSmrg        p = XtCalloc(2, SIZE_MAX);
381fdf6a26fSmrg        g_assert_null(p);
382fdf6a26fSmrg    } else {
383fdf6a26fSmrg        /*
384fdf6a26fSmrg         * We jumped here from error handler as expected.
385fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
386fdf6a26fSmrg         * calls that override errno, when trying to load error message
387fdf6a26fSmrg         * files from different locations.
388fdf6a26fSmrg         */
389fdf6a26fSmrg    }
390fdf6a26fSmrg
391fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
392fdf6a26fSmrg        /* SQRT_SIZE_MAX * SQRT_SIZE_MAX == 0 due to overflow */
393fdf6a26fSmrg        p = XtCalloc(SQRT_SIZE_MAX, SQRT_SIZE_MAX);
394fdf6a26fSmrg        g_assert_null(p);
395fdf6a26fSmrg    } else {
396fdf6a26fSmrg        /*
397fdf6a26fSmrg         * We jumped here from error handler as expected.
398fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
399fdf6a26fSmrg         * calls that override errno, when trying to load error message
400fdf6a26fSmrg         * files from different locations.
401fdf6a26fSmrg         */
402fdf6a26fSmrg    }
403fdf6a26fSmrg
404fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
405fdf6a26fSmrg        /* Overflows to a small positive number */
406fdf6a26fSmrg        p = XtCalloc(SQRT_SIZE_MAX + 1, SQRT_SIZE_MAX);
407fdf6a26fSmrg        g_assert_null(p);
408fdf6a26fSmrg    } else {
409fdf6a26fSmrg        /*
410fdf6a26fSmrg         * We jumped here from error handler as expected.
411fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
412fdf6a26fSmrg         * calls that override errno, when trying to load error message
413fdf6a26fSmrg         * files from different locations.
414fdf6a26fSmrg         */
415fdf6a26fSmrg    }
416fdf6a26fSmrg#endif
417fdf6a26fSmrg}
418fdf6a26fSmrg
419fdf6a26fSmrg/* Make sure XtRealloc() works for a non-zero amount of memory */
420fdf6a26fSmrgstatic void test_XtRealloc_normal(void)
421fdf6a26fSmrg{
422fdf6a26fSmrg    void *p, *p2;
423fdf6a26fSmrg    char *p3;
424fdf6a26fSmrg
425fdf6a26fSmrg    errno = 0;
426fdf6a26fSmrg
427fdf6a26fSmrg    /* Make sure realloc with a NULL pointer acts as malloc */
428fdf6a26fSmrg    p = XtRealloc(NULL, 814);
429fdf6a26fSmrg    g_assert_nonnull(p);
430fdf6a26fSmrg    CHECK_ALIGNMENT(p);
431fdf6a26fSmrg    CHECK_SIZE(p, 814);
432fdf6a26fSmrg
433fdf6a26fSmrg    /* make sure we can write to all the allocated memory */
434fdf6a26fSmrg    memset(p, 'A', 814);
435fdf6a26fSmrg
436fdf6a26fSmrg    /* create another block after the first */
437fdf6a26fSmrg    p2 = XtMalloc(73);
438fdf6a26fSmrg    g_assert_nonnull(p2);
439fdf6a26fSmrg
440fdf6a26fSmrg    /* now resize the first */
441fdf6a26fSmrg    p3 = XtRealloc(p, 7314);
442fdf6a26fSmrg    g_assert_nonnull(p3);
443fdf6a26fSmrg    CHECK_ALIGNMENT(p3);
444fdf6a26fSmrg    CHECK_SIZE(p3, 7314);
445fdf6a26fSmrg
446fdf6a26fSmrg    /* verify previous values are still present */
447fdf6a26fSmrg    for (int i = 0; i < 814; i++) {
448fdf6a26fSmrg        g_assert_cmpint(p3[i], ==, 'A');
449fdf6a26fSmrg    }
450fdf6a26fSmrg
451fdf6a26fSmrg    XtFree(p3);
452fdf6a26fSmrg    XtFree(p2);
453fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
454fdf6a26fSmrg}
455fdf6a26fSmrg
456fdf6a26fSmrg/* Make sure XtRealloc(0) returns a valid pointer as expected */
457fdf6a26fSmrgstatic void test_XtRealloc_zero(void)
458fdf6a26fSmrg{
459fdf6a26fSmrg    void *p, *p2;
460fdf6a26fSmrg
461fdf6a26fSmrg    errno = 0;
462fdf6a26fSmrg
463fdf6a26fSmrg    p = XtRealloc(NULL, 0);
464fdf6a26fSmrg    g_assert_nonnull(p);
465fdf6a26fSmrg
466fdf6a26fSmrg    p2 = XtRealloc(p, 0);
467fdf6a26fSmrg#ifdef MALLOC_0_RETURNS_NULL
468fdf6a26fSmrg    g_assert_null(p);
469fdf6a26fSmrg#else
470fdf6a26fSmrg    g_assert_nonnull(p);
471fdf6a26fSmrg#endif
472fdf6a26fSmrg
473fdf6a26fSmrg    XtFree(p2);
474fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
475fdf6a26fSmrg}
476fdf6a26fSmrg
477fdf6a26fSmrg/* Make sure sizes larger than the limit we set in main() fail */
478fdf6a26fSmrgstatic void test_XtRealloc_oversize(void)
479fdf6a26fSmrg{
480fdf6a26fSmrg    void *p, *p2;
481fdf6a26fSmrg
482fdf6a26fSmrg    /* Pick a size between 1 & 256K */
483fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (256 * 1024));
484fdf6a26fSmrg
485fdf6a26fSmrg    p = XtRealloc(NULL, size);
486fdf6a26fSmrg    g_assert_nonnull(p);
487fdf6a26fSmrg    CHECK_ALIGNMENT(p);
488fdf6a26fSmrg
489fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
490fdf6a26fSmrg        p2 = XtRealloc(p, ALLOC_LIMIT + 1);
491fdf6a26fSmrg        g_assert_null(p2);
492fdf6a26fSmrg    } else {
493fdf6a26fSmrg        /*
494fdf6a26fSmrg         * We jumped here from error handler as expected.
495fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
496fdf6a26fSmrg         * calls that override errno, when trying to load error message
497fdf6a26fSmrg         * files from different locations.
498fdf6a26fSmrg         */
499fdf6a26fSmrg    }
500fdf6a26fSmrg
501fdf6a26fSmrg    errno = 0;
502fdf6a26fSmrg    XtFree(p);
503fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
504fdf6a26fSmrg}
505fdf6a26fSmrg
506fdf6a26fSmrg/* Make sure XtRealloc catches integer overflow if possible, by requesting
507fdf6a26fSmrg * sizes that are so large that they cause overflows when either adding the
508fdf6a26fSmrg * realloc data block overhead or aligning.
509fdf6a26fSmrg *
510fdf6a26fSmrg * Testing integer overflow cases is limited by the fact that XtRealloc
511fdf6a26fSmrg * only takes unsigned arguments (typically 32-bit), and relies on
512fdf6a26fSmrg * the underlying libc realloc to catch overflow, which can't occur if
513fdf6a26fSmrg * 32-bit arguments are passed to a function taking 64-bit args.
514fdf6a26fSmrg */
515fdf6a26fSmrgstatic void test_XtRealloc_overflow(void)
516fdf6a26fSmrg{
517fdf6a26fSmrg#if UINT_MAX < SIZE_MAX
518fdf6a26fSmrg    g_test_skip("overflow not possible in this config");
519fdf6a26fSmrg#else
520fdf6a26fSmrg    void *p, *p2;
521fdf6a26fSmrg
522fdf6a26fSmrg    /* Pick a size between 1 & 256K */
523fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (256 * 1024));
524fdf6a26fSmrg
525fdf6a26fSmrg    p = XtRealloc(NULL, size);
526fdf6a26fSmrg    g_assert_nonnull(p);
527fdf6a26fSmrg    CHECK_ALIGNMENT(p);
528fdf6a26fSmrg
529fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
530fdf6a26fSmrg        p2 = XtRealloc(p, SIZE_MAX);
531fdf6a26fSmrg        g_assert_null(p2);
532fdf6a26fSmrg    } else {
533fdf6a26fSmrg        /*
534fdf6a26fSmrg         * We jumped here from error handler as expected.
535fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
536fdf6a26fSmrg         * calls that override errno, when trying to load error message
537fdf6a26fSmrg         * files from different locations.
538fdf6a26fSmrg         */
539fdf6a26fSmrg    }
540fdf6a26fSmrg
541fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
542fdf6a26fSmrg        p2 = XtRealloc(p, SIZE_MAX - 1);
543fdf6a26fSmrg        g_assert_null(p2);
544fdf6a26fSmrg    } else {
545fdf6a26fSmrg        /*
546fdf6a26fSmrg         * We jumped here from error handler as expected.
547fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
548fdf6a26fSmrg         * calls that override errno, when trying to load error message
549fdf6a26fSmrg         * files from different locations.
550fdf6a26fSmrg         */
551fdf6a26fSmrg    }
552fdf6a26fSmrg
553fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
554fdf6a26fSmrg        p2 = XtRealloc(p, SIZE_MAX - 8);
555fdf6a26fSmrg        g_assert_null(p2);
556fdf6a26fSmrg    } else {
557fdf6a26fSmrg        /*
558fdf6a26fSmrg         * We jumped here from error handler as expected.
559fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
560fdf6a26fSmrg         * calls that override errno, when trying to load error message
561fdf6a26fSmrg         * files from different locations.
562fdf6a26fSmrg         */
563fdf6a26fSmrg    }
564fdf6a26fSmrg
565fdf6a26fSmrg    errno = 0;
566fdf6a26fSmrg    XtFree(p);
567fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
568fdf6a26fSmrg#endif
569fdf6a26fSmrg}
570fdf6a26fSmrg
571fdf6a26fSmrg
572fdf6a26fSmrg/* Make sure XtReallocArray() works for a non-zero amount of memory */
573fdf6a26fSmrgstatic void test_XtReallocArray_normal(void)
574fdf6a26fSmrg{
575fdf6a26fSmrg    void *p, *p2;
576fdf6a26fSmrg    char *p3;
577fdf6a26fSmrg
578fdf6a26fSmrg    errno = 0;
579fdf6a26fSmrg
580fdf6a26fSmrg    /* Make sure reallocarray with a NULL pointer acts as malloc */
581fdf6a26fSmrg    p = XtReallocArray(NULL, 8, 14);
582fdf6a26fSmrg    g_assert_nonnull(p);
583fdf6a26fSmrg    CHECK_ALIGNMENT(p);
584fdf6a26fSmrg    CHECK_SIZE(p, 8 * 14);
585fdf6a26fSmrg
586fdf6a26fSmrg    /* make sure we can write to all the allocated memory */
587fdf6a26fSmrg    memset(p, 'A', 8 * 14);
588fdf6a26fSmrg
589fdf6a26fSmrg    /* create another block after the first */
590fdf6a26fSmrg    p2 = XtMalloc(73);
591fdf6a26fSmrg    g_assert_nonnull(p2);
592fdf6a26fSmrg
593fdf6a26fSmrg    /* now resize the first */
594fdf6a26fSmrg    p3 = XtReallocArray(p, 73, 14);
595fdf6a26fSmrg    g_assert_nonnull(p3);
596fdf6a26fSmrg    CHECK_ALIGNMENT(p3);
597fdf6a26fSmrg    CHECK_SIZE(p3, 73 * 14);
598fdf6a26fSmrg    /* verify previous values are still present */
599fdf6a26fSmrg    for (int i = 0; i < (8 * 14); i++) {
600fdf6a26fSmrg        g_assert_cmpint(p3[i], ==, 'A');
601fdf6a26fSmrg    }
602fdf6a26fSmrg
603fdf6a26fSmrg    XtFree(p3);
604fdf6a26fSmrg    XtFree(p2);
605fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
6069e7bcd65Smrg}
6079e7bcd65Smrg
608fdf6a26fSmrg/* Make sure XtReallocArray(0) returns a valid pointer as expected */
609fdf6a26fSmrgstatic void test_XtReallocArray_zero(void)
610fdf6a26fSmrg{
611fdf6a26fSmrg    void *p, *p2;
612fdf6a26fSmrg
613fdf6a26fSmrg    errno = 0;
614fdf6a26fSmrg
615fdf6a26fSmrg    p = XtReallocArray(NULL, 0, 0);
616fdf6a26fSmrg    g_assert_nonnull(p);
617fdf6a26fSmrg
618fdf6a26fSmrg    p2 = XtReallocArray(p, 0, 0);
619fdf6a26fSmrg#ifdef MALLOC_0_RETURNS_NULL
620fdf6a26fSmrg    g_assert_null(p);
621fdf6a26fSmrg#else
622fdf6a26fSmrg    g_assert_nonnull(p);
623fdf6a26fSmrg#endif
624fdf6a26fSmrg
625fdf6a26fSmrg    XtFree(p2);
626fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
627fdf6a26fSmrg}
628fdf6a26fSmrg
629fdf6a26fSmrg/* Make sure sizes larger than the limit we set in main() fail */
630fdf6a26fSmrgstatic void test_XtReallocArray_oversize(void)
631fdf6a26fSmrg{
632fdf6a26fSmrg    void *p, *p2;
633fdf6a26fSmrg
634fdf6a26fSmrg    /* Pick a number of elements between 1 & 16K */
635fdf6a26fSmrg    guint32 num = g_test_rand_int_range(1, (16 * 1024));
636fdf6a26fSmrg    /* Pick a size between 1 & 16K */
637fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (16 * 1024));
638fdf6a26fSmrg
639fdf6a26fSmrg    p = XtReallocArray(NULL, num, size);
640fdf6a26fSmrg    g_assert_nonnull(p);
641fdf6a26fSmrg    CHECK_ALIGNMENT(p);
642fdf6a26fSmrg    CHECK_SIZE(p, num * size);
643fdf6a26fSmrg
644fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
645fdf6a26fSmrg        p2 = XtReallocArray(p, 2, ALLOC_LIMIT);
646fdf6a26fSmrg        g_assert_null(p2);
647fdf6a26fSmrg    } else {
648fdf6a26fSmrg        /*
649fdf6a26fSmrg         * We jumped here from error handler as expected.
650fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
651fdf6a26fSmrg         * calls that override errno, when trying to load error message
652fdf6a26fSmrg         * files from different locations.
653fdf6a26fSmrg         */
654fdf6a26fSmrg    }
655fdf6a26fSmrg
656fdf6a26fSmrg    errno = 0;
657fdf6a26fSmrg    XtFree(p);
658fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
659fdf6a26fSmrg}
660fdf6a26fSmrg
661fdf6a26fSmrg/* Make sure XtReallocArray catches integer overflow if possible, by requesting
662fdf6a26fSmrg * sizes that are so large that they cause overflows when either adding the
663fdf6a26fSmrg * reallocarray data block overhead or aligning.
664fdf6a26fSmrg *
665fdf6a26fSmrg * Testing integer overflow cases is limited by the fact that XtReallocArray
666fdf6a26fSmrg * only takes unsigned arguments (typically 32-bit), and relies on
667fdf6a26fSmrg * the underlying libc reallocarray to catch overflow, which can't occur if
668fdf6a26fSmrg * 32-bit arguments are passed to a function taking 64-bit args.
669fdf6a26fSmrg */
670fdf6a26fSmrgstatic void test_XtReallocArray_overflow(void)
671fdf6a26fSmrg{
672fdf6a26fSmrg#if UINT_MAX < SIZE_MAX
673fdf6a26fSmrg    g_test_skip("overflow not possible in this config");
674fdf6a26fSmrg#else
675fdf6a26fSmrg    void *p, *p2;
676fdf6a26fSmrg
677fdf6a26fSmrg    /* Pick a number of elements between 1 & 16K */
678fdf6a26fSmrg    guint32 num = g_test_rand_int_range(1, (16 * 1024));
679fdf6a26fSmrg    /* Pick a size between 1 & 16K */
680fdf6a26fSmrg    guint32 size = g_test_rand_int_range(1, (16 * 1024));
681fdf6a26fSmrg
682fdf6a26fSmrg    p = XtReallocArray(NULL, num, size);
683fdf6a26fSmrg    g_assert_nonnull(p);
684fdf6a26fSmrg    CHECK_ALIGNMENT(p);
685fdf6a26fSmrg    CHECK_SIZE(p, num * size);
686fdf6a26fSmrg
687fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
688fdf6a26fSmrg        p2 = XtReallocArray(p, 1, SIZE_MAX);
689fdf6a26fSmrg        g_assert_null(p2);
690fdf6a26fSmrg    } else {
691fdf6a26fSmrg        /*
692fdf6a26fSmrg         * We jumped here from error handler as expected.
693fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
694fdf6a26fSmrg         * calls that override errno, when trying to load error message
695fdf6a26fSmrg         * files from different locations.
696fdf6a26fSmrg         */
697fdf6a26fSmrg    }
698fdf6a26fSmrg
699fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
700fdf6a26fSmrg        /* SQRT_SIZE_MAX * SQRT_SIZE_MAX == 0 due to overflow */
701fdf6a26fSmrg        p2 = XtReallocArray(p, SQRT_SIZE_MAX, SQRT_SIZE_MAX);
702fdf6a26fSmrg        g_assert_null(p2);
703fdf6a26fSmrg    } else {
704fdf6a26fSmrg        /*
705fdf6a26fSmrg         * We jumped here from error handler as expected.
706fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
707fdf6a26fSmrg         * calls that override errno, when trying to load error message
708fdf6a26fSmrg         * files from different locations.
709fdf6a26fSmrg         */
710fdf6a26fSmrg    }
711fdf6a26fSmrg
712fdf6a26fSmrg    if (setjmp(jmp_env) == 0) {
713fdf6a26fSmrg        /* Overflows to a small positive number */
714fdf6a26fSmrg        p2 = XtReallocArray(p, SQRT_SIZE_MAX + 1, SQRT_SIZE_MAX);
715fdf6a26fSmrg        g_assert_null(p2);
716fdf6a26fSmrg    } else {
717fdf6a26fSmrg        /*
718fdf6a26fSmrg         * We jumped here from error handler as expected.
719fdf6a26fSmrg         * We cannot verify errno here, as the Xt error handler makes
720fdf6a26fSmrg         * calls that override errno, when trying to load error message
721fdf6a26fSmrg         * files from different locations.
722fdf6a26fSmrg         */
723fdf6a26fSmrg    }
724fdf6a26fSmrg
725fdf6a26fSmrg    errno = 0;
726fdf6a26fSmrg    XtFree(p);
727fdf6a26fSmrg    g_assert_cmpint(errno, ==, 0);
728fdf6a26fSmrg#endif
729fdf6a26fSmrg}
730fdf6a26fSmrg
731fdf6a26fSmrg
7329e7bcd65Smrgint main(int argc, char** argv)
7339e7bcd65Smrg{
734fdf6a26fSmrg    struct rlimit lim;
735fdf6a26fSmrg
7369e7bcd65Smrg    program_name = argv[0];
7379e7bcd65Smrg
7389e7bcd65Smrg    g_test_init(&argc, &argv, NULL);
739fdf6a26fSmrg    g_test_bug_base("https://gitlab.freedesktop.org/xorg/lib/libxt/-/issues/");
740fdf6a26fSmrg
741fdf6a26fSmrg    /* Set a memory limit so we can test allocations over that size fail */
742fdf6a26fSmrg    g_assert_no_errno(getrlimit(RLIMIT_AS, &lim));
743fdf6a26fSmrg    if (lim.rlim_cur > ALLOC_LIMIT) {
744fdf6a26fSmrg        lim.rlim_cur = ALLOC_LIMIT;
745fdf6a26fSmrg        g_assert_no_errno(setrlimit(RLIMIT_AS, &lim));
746fdf6a26fSmrg    }
747fdf6a26fSmrg
748fdf6a26fSmrg    /* Install xt_error_handler to avoid exit on allocation failure */
749fdf6a26fSmrg    XtSetErrorHandler(xt_error_handler);
7509e7bcd65Smrg
7519e7bcd65Smrg    g_test_add_func("/Alloc/XtAsprintf/short", test_XtAsprintf_short);
7529e7bcd65Smrg    g_test_add_func("/Alloc/XtAsprintf/long", test_XtAsprintf_long);
7539e7bcd65Smrg
754fdf6a26fSmrg    g_test_add_func("/Alloc/XtMalloc/normal", test_XtMalloc_normal);
755fdf6a26fSmrg    g_test_add_func("/Alloc/XtMalloc/zero", test_XtMalloc_zero);
756fdf6a26fSmrg    g_test_add_func("/Alloc/XtMalloc/oversize", test_XtMalloc_oversize);
757fdf6a26fSmrg    g_test_add_func("/Alloc/XtMalloc/overflow", test_XtMalloc_overflow);
758fdf6a26fSmrg
759fdf6a26fSmrg    g_test_add_func("/Alloc/XtCalloc/normal", test_XtCalloc_normal);
760fdf6a26fSmrg    g_test_add_func("/Alloc/XtCalloc/zero", test_XtCalloc_zero);
761fdf6a26fSmrg    g_test_add_func("/Alloc/XtCalloc/oversize", test_XtCalloc_oversize);
762fdf6a26fSmrg    g_test_add_func("/Alloc/XtCalloc/overflow", test_XtCalloc_overflow);
763fdf6a26fSmrg
764fdf6a26fSmrg    g_test_add_func("/Alloc/XtRealloc/normal", test_XtRealloc_normal);
765fdf6a26fSmrg    g_test_add_func("/Alloc/XtRealloc/zero", test_XtRealloc_zero);
766fdf6a26fSmrg    g_test_add_func("/Alloc/XtRealloc/oversize", test_XtRealloc_oversize);
767fdf6a26fSmrg    g_test_add_func("/Alloc/XtRealloc/overflow", test_XtRealloc_overflow);
768fdf6a26fSmrg
769fdf6a26fSmrg    g_test_add_func("/Alloc/XtReallocArray/normal", test_XtReallocArray_normal);
770fdf6a26fSmrg    g_test_add_func("/Alloc/XtReallocArray/zero", test_XtReallocArray_zero);
771fdf6a26fSmrg    g_test_add_func("/Alloc/XtReallocArray/oversize",
772fdf6a26fSmrg                    test_XtReallocArray_oversize);
773fdf6a26fSmrg    g_test_add_func("/Alloc/XtReallocArray/overflow",
774fdf6a26fSmrg                    test_XtReallocArray_overflow);
775fdf6a26fSmrg
7769e7bcd65Smrg    return g_test_run();
7779e7bcd65Smrg}
778