/* Test of immutable data. Copyright (C) 2021-2023 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* Written by Bruno Haible , 2021. */ #include #include "immutable.h" #include #include #include #include "macros.h" struct data { int x; long y; }; #if IMMUTABLE_EFFECTIVE static _GL_ASYNC_SAFE _Noreturn void segv_handler (int signo) { _Exit (0); } static void install_segv_handler (void) { signal (SIGSEGV, segv_handler); # if (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ signal (SIGBUS, segv_handler); # endif } #endif int main (int argc, char *argv[]) { if (argc != 2) { fprintf (stderr, "%s: need 1 argument\n", argv[0]); return 1; } int test = atoi (argv[1]); switch (test) { case 0: /* Indicates whether the implementation effectively rejects writes to immutable data. */ #if !IMMUTABLE_EFFECTIVE fputs ("Skipping test: immutability cannot be enforced\n", stderr); return 77; #else break; #endif case 1: /* Correct use of immmalloc. */ { struct data *wp; struct data const *p; wp = (struct data *) immmalloc (sizeof (struct data)); ASSERT (wp != NULL); wp->x = 7; wp->y = 42; p = immfreeze (wp); ASSERT (p->x == 7); ASSERT (p->y == 42); immfree (p); } break; case 2: /* Catch invalid write access. */ { struct data *wp; struct data const *p; wp = (struct data *) immmalloc (sizeof (struct data)); ASSERT (wp != NULL); wp->x = 7; wp->y = 42; p = immfreeze (wp); #if IMMUTABLE_EFFECTIVE install_segv_handler (); #endif /* This assignment should crash. */ ((struct data *) p)->y = 77; #if IMMUTABLE_EFFECTIVE return 1; #endif } break; case 3: /* Catch invalid write access while another data object is not frozen. */ { struct data *wp; struct data const *p; struct data *wp2; wp = (struct data *) immmalloc (sizeof (struct data)); ASSERT (wp != NULL); wp->x = 7; wp->y = 42; p = immfreeze (wp); ASSERT (p->x == 7); ASSERT (p->y == 42); wp2 = (struct data *) immmalloc (sizeof (struct data)); ASSERT (wp2 != NULL); wp2->x = 7; #if IMMUTABLE_EFFECTIVE install_segv_handler (); #endif /* This assignment should crash. */ ((struct data *) p)->y = 42; #if IMMUTABLE_EFFECTIVE return 1; #endif } break; case 4: /* Correct use of immstrdup. */ { const char *s = immstrdup ("Hello"); ASSERT (strlen (s) == 5); ASSERT (strcmp (s, "Hello") == 0); immfree (s); } break; default: ASSERT (false); } return 0; }