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