dumatest.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * DUMA - Red-Zone memory allocator.
  3. * Copyright (C) 2020-2022 Jeffrey H. Johnson <trnsz@pobox.com>
  4. * Copyright (C) 2002-2021 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
  5. * Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
  6. * License: GNU GPL (GNU General Public License, see COPYING-GPL)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. *
  22. *
  23. * FILE CONTENTS:
  24. * DUMA confidence tests.
  25. * Make sure all of the various functions of DUMA work correctly.
  26. */
  27. #ifdef __GLIBC__
  28. #ifndef _POSIX_C_SOURCE
  29. #define _POSIX_C_SOURCE 1
  30. #define _XOPEN_SOURCE 700
  31. #define _ISOC99_SOURCE
  32. #define _POSIX_C_SOURCE 199309L
  33. #endif /* ifndef _POSIX_C_SOURCE */
  34. #endif /* ifdef __GLIBC__ */
  35. #ifndef _GNU_SOURCE
  36. #define _GNU_SOURCE 1
  37. #endif /* ifndef _GNU_SOURCE */
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  42. #include <unistd.h>
  43. #else /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  44. #include <io.h>
  45. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  46. #include <setjmp.h>
  47. #include <signal.h>
  48. #include "../duma.h"
  49. #ifndef PAGE_PROTECTION_VIOLATED_SIGNAL
  50. /* changed default in code below to use two signals: SIGSEGV and SIGBUS */
  51. /* #define PAGE_PROTECTION_VIOLATED_SIGNAL SIGSEGV */
  52. #endif /* ifndef PAGE_PROTECTION_VIOLATED_SIGNAL */
  53. struct diagnostic
  54. {
  55. int (*test) (void); /* pointer to some test function returning int */
  56. int expectedStatus; /* expected return value/status */
  57. const char *explanation; /* explanation of that test */
  58. };
  59. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  60. static sigjmp_buf env;
  61. #else /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  62. static jmp_buf env;
  63. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  64. /*
  65. * There is still too little standardization of the arguments and return
  66. * type of signal handler functions.
  67. */
  68. static void
  69. segmentationFaultHandler(int signalNumber
  70. #if ( defined( _AIX ))
  71. ,
  72. ...
  73. #endif /* if ( defined( _AIX )) */
  74. )
  75. {
  76. (void)signalNumber;
  77. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  78. siglongjmp(env, 1);
  79. #else /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  80. longjmp(env, 1);
  81. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  82. }
  83. static int
  84. gotSegmentationFault(int (*test ) (void))
  85. {
  86. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  87. sigset_t newmask, oldmask;
  88. int savemask;
  89. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  90. #ifdef PAGE_PROTECTION_VIOLATED_SIGNAL
  91. void (*oldhandler) (int) = SIG_ERR;
  92. #else /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  93. void (*oldSIGSEGVhandler) (int) = SIG_ERR;
  94. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  95. void ( *oldSIGBUShandler )(int) = SIG_ERR;
  96. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  97. #endif /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  98. int status;
  99. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  100. if (0 == sigsetjmp(env, savemask))
  101. #else /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  102. if (0 == setjmp(env))
  103. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  104. {
  105. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  106. /* unblock signal and save previous signal mask */
  107. sigemptyset(&newmask);
  108. #ifdef PAGE_PROTECTION_VIOLATED_SIGNAL
  109. sigaddset(&newmask, PAGE_PROTECTION_VIOLATED_SIGNAL);
  110. #else /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  111. sigaddset(&newmask, SIGSEGV);
  112. sigaddset(&newmask, SIGBUS);
  113. #endif /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  114. sigprocmask(SIG_UNBLOCK, &newmask, &oldmask);
  115. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  116. #ifdef PAGE_PROTECTION_VIOLATED_SIGNAL
  117. oldhandler
  118. = signal(PAGE_PROTECTION_VIOLATED_SIGNAL, segmentationFaultHandler);
  119. #else /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  120. oldSIGSEGVhandler = signal(SIGSEGV, segmentationFaultHandler);
  121. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  122. oldSIGBUShandler = signal(SIGBUS, segmentationFaultHandler);
  123. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  124. #endif /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  125. status = ( *test )();
  126. }
  127. else
  128. {
  129. status = 1;
  130. }
  131. /* install previous signal handler */
  132. #ifdef PAGE_PROTECTION_VIOLATED_SIGNAL
  133. if (SIG_ERR != oldhandler)
  134. {
  135. signal(PAGE_PROTECTION_VIOLATED_SIGNAL, oldhandler);
  136. }
  137. #else /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  138. if (SIG_ERR != oldSIGSEGVhandler)
  139. {
  140. signal(SIGSEGV, oldSIGSEGVhandler);
  141. }
  142. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  143. if (SIG_ERR != oldSIGBUShandler)
  144. {
  145. signal(SIGBUS, oldSIGBUShandler);
  146. }
  147. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  148. #endif /* ifdef PAGE_PROTECTION_VIOLATED_SIGNAL */
  149. #if !defined( WIN32 ) || defined( __CYGWIN__ )
  150. /* restore signal mask */
  151. sigprocmask(SIG_SETMASK, &oldmask, NULL);
  152. #endif /* if !defined( WIN32 ) || defined( __CYGWIN__ ) */
  153. return ( status );
  154. }
  155. static char *allocation = (char *)0;
  156. /* c is global so that assignments to it won't be optimized out. */
  157. char c;
  158. static int
  159. testSizes(void)
  160. {
  161. /*
  162. * If DUMA_ADDR can't hold all of the bits of a void *,
  163. * have the user call createconf.
  164. */
  165. size_t sd = sizeof ( DUMA_ADDR );
  166. size_t sv = sizeof ( void * );
  167. return ( sd < sv );
  168. }
  169. static int
  170. allocateMemory(void)
  171. {
  172. allocation = (char *)malloc(1);
  173. if (allocation != (char *)0)
  174. {
  175. return ( 0 );
  176. }
  177. else
  178. {
  179. return ( 1 );
  180. }
  181. }
  182. static int
  183. freeMemory(void)
  184. {
  185. free(allocation);
  186. allocation = (char *)0;
  187. return ( 0 );
  188. }
  189. static int
  190. protectBelow(void)
  191. {
  192. DUMA_SET_PROTECT_BELOW(1);
  193. return ( 0 );
  194. }
  195. static int
  196. protectAbove(void)
  197. {
  198. DUMA_SET_PROTECT_BELOW(0);
  199. return ( 0 );
  200. }
  201. static int
  202. read0(void)
  203. {
  204. c = *allocation;
  205. return ( 0 );
  206. }
  207. static int
  208. write0(void)
  209. {
  210. *allocation = 1;
  211. return ( 0 );
  212. }
  213. static int
  214. read1(void)
  215. {
  216. c = allocation[1];
  217. return ( 0 );
  218. }
  219. static int
  220. readMinus1(void)
  221. {
  222. c = allocation[-1];
  223. return ( 0 );
  224. }
  225. static struct diagnostic diagnostics[] = {
  226. { testSizes,
  227. 0,
  228. "Please add -DLONG_LONG to the compiler flags and recompile." },
  229. #if 1
  230. { protectAbove,
  231. 0,
  232. "Protect above: This sets DUMA to protect\n"
  233. "the upper boundary of a malloc buffer, rather than the lower boundary." },
  234. { allocateMemory,
  235. 0,
  236. "Allocation 1: This test allocates a single byte of memory." },
  237. { read0,
  238. 0,
  239. "Read valid memory 1: This test reads the allocated memory." },
  240. { write0,
  241. 0,
  242. "Write valid memory 1: This test writes the allocated memory." },
  243. { readMinus1,
  244. 0,
  245. "Read underrun: This test reads before the beginning of the buffer." },
  246. { read1,
  247. 1,
  248. "Read overrun: This test reads beyond the end of the buffer." },
  249. { freeMemory,
  250. 0,
  251. "Free memory 1: This test frees the allocated memory." },
  252. #endif /* if 1 */
  253. #if 1
  254. { protectBelow,
  255. 0,
  256. "Protect below: This sets DUMA to protect\n"
  257. "the lower boundary of a malloc buffer, rather than the upper boundary." },
  258. { allocateMemory,
  259. 0,
  260. "Allocation 2: This allocates memory with the lower boundary protected." },
  261. { read0,
  262. 0,
  263. "Read valid memory 2: This test reads the allocated memory." },
  264. { write0,
  265. 0,
  266. "Write valid memory 2: This test writes the allocated memory." },
  267. { readMinus1,
  268. 1,
  269. "Read underrun: This test reads before the beginning of the buffer." },
  270. { freeMemory,
  271. 0,
  272. "Free memory 2: This test frees the allocated memory." },
  273. #endif /* if 1 */
  274. { 0,
  275. 0,
  276. 0 }
  277. };
  278. static const char failedTest[] = "DUMA confidence test failed.\n";
  279. static const char newline = '\n';
  280. int
  281. main(int argc, char **argv)
  282. {
  283. static const struct diagnostic *diag = diagnostics;
  284. int testno;
  285. (void)argc;
  286. (void)argv;
  287. #ifdef DUMA_EXPLICIT_INIT
  288. duma_init();
  289. #endif /* ifdef DUMA_EXPLICIT_INIT */
  290. DUMA_SET_PROTECT_BELOW(0);
  291. DUMA_SET_ALIGNMENT(DUMA_MIN_ALIGNMENT);
  292. allocation = 0;
  293. for (testno = 0; diag->explanation != 0; ++testno, ++diag)
  294. {
  295. int status;
  296. #if 0
  297. write(0, diag->explanation, strlen(diag->explanation));
  298. write(0, &newline, 1);
  299. #endif /* if 0 */
  300. status = gotSegmentationFault(diag->test);
  301. if (status != diag->expectedStatus)
  302. {
  303. /*
  304. * Don't use stdio to print here, because stdio
  305. * uses malloc() and we've just proven that malloc()
  306. * is broken. Also, use _exit() instead of exit(),
  307. * because _exit() doesn't flush stdio.
  308. */
  309. write(2, failedTest, sizeof ( failedTest ) - 1);
  310. write(2, diag->explanation, strlen(diag->explanation));
  311. write(2, &newline, 1);
  312. _exit(-1);
  313. }
  314. }
  315. /* avoid memory leak */
  316. if (allocation)
  317. {
  318. freeMemory();
  319. }
  320. #if 0
  321. {
  322. char * dynmemA;
  323. char * dynmemB;
  324. /* test for DUMA_CHECK_FREQ */
  325. printf("0\n");
  326. protectAbove();
  327. printf("1\n");
  328. dynmemA = (char*)malloc( 10 * sizeof ( char ) );
  329. printf("2\n");
  330. dynmemA[-1 ] = 0;
  331. printf("3\n");
  332. dynmemB = (char*)malloc( 11 * sizeof ( char ) );
  333. printf("4\n");
  334. free( dynmemB );
  335. printf("5\n");
  336. free( dynmemA );
  337. printf("6\n");
  338. }
  339. #endif /* if 0 */
  340. return ( 0 );
  341. }