home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume21 / malloc-debug / part01 next >
Text File  |  1991-07-25  |  45KB  |  2,026 lines

  1. Newsgroups: comp.sources.misc
  2. From: Brandon S. Allbery KF8NH <allbery@NCoast.ORG>
  3. Subject:  v21i041:  malloc-debug - Debugging malloc package, Part01/01
  4. Message-ID: <1991Jul25.024036.28795@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: 653244e446b6a32e5d8b5f3545ca4ba5
  6. Date: Thu, 25 Jul 1991 02:40:36 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Brandon S. Allbery KF8NH <allbery@NCoast.ORG>
  10. Posting-number: Volume 21, Issue 41
  11. Archive-name: malloc-debug/part01
  12. Environment: UNIX
  13.  
  14. [ This supersedes X-Archive: comp.sources.misc/8707/59  -Kent+ ]
  15.  
  16. Some years ago, I posted a debugging malloc package to the net.  This is the
  17. latest version of that package.
  18.  
  19. Features:
  20.  
  21. * Catches writes to either side of malloc'ed memory.
  22. * Checks the malloc pool for consistency on each call to malloc, free, realloc,
  23.   or calloc; prints a diagnostic dump if the pool is corrupted.
  24. * User checks can be made by calling _mallchk("string ID").
  25. * If MALLOC_TRACEBACK is defined, a stack trace will be printed when the pool
  26.   check fails.  Since the stack is often irrecoverably corrupted by the time
  27.   a core file is generated, this traceback can sometimes be the only way to
  28.   find out where the error was detected.  Only tested on 386 SVR3.[12].
  29. * Traps SIGBUS and SIGSEGV and dumps the malloc pool; these often indicate
  30.   "wild" pointers.
  31. * Environment $MALLOC_OPTS controls tracing:
  32.   'v'    trace entry/exit of functions
  33.   't'    stack traceback (if MALLOC_TRACEBACK) of functions
  34.   'V'    trace entry/exit of utility functions
  35.   'T'    stack traceback of utility functions
  36.   'm'    fault program if malloc(0) or realloc(*, 0) called
  37.   'b'    print details on allocated blocks
  38.   'f'    fault program on free(0)
  39.   'u'    attempt to release free()'d memory to system with sbrk()
  40.   'r'    fault program if realloc(0, ...)
  41.   'S'    dump malloc pool on SIGSEGV
  42.   'B'    dump malloc pool on SIGBUS
  43. * Provides alternate versions of several utility functions if MALLOC_LIB is
  44.   defined; these functions will trap many "wild pointer" or off-by-one errors
  45.   before they trash memory, and will provide an immediate indication of the
  46.   location of such bugs.
  47.  
  48. ++Brandon
  49. -------------------------------------------------------------------------------
  50. # This is a shell archive.  Save this into a file, edit it
  51. # and delete all lines above this comment.  Then give this
  52. # file to sh by executing the command "sh file".  The files
  53. # will be extracted into the current directory owned by
  54. # you with default permissions.
  55. #
  56. # The files contained herein are:
  57. #        malloc.c       malloc.h     malltest.c
  58. #
  59. echo 'x - malloc.c'
  60. sed 's/^X//' <<'________This_Is_The_END________' >>malloc.c
  61. X/*
  62. X * malloc for debugging -- allocates via sbrk and tracks stuff, does diag dump
  63. X * if things appear to be screwed up
  64. X */
  65. X
  66. X#include <signal.h>
  67. X#include <fcntl.h>
  68. X#include "malloc.h"
  69. X
  70. X#ifndef MALLOC_DEFAULT
  71. X#define MALLOC_DEFAULT 0
  72. X#endif
  73. X
  74. X#ifndef MALLOC_LIMIT
  75. X#define MALLOC_LIMIT (char *) 0x80000000
  76. X#endif
  77. X
  78. X#ifndef sigbase_t
  79. X#define sigbase_t void
  80. X#endif
  81. X
  82. Xtypedef sigbase_t (*sighand_t)();
  83. X
  84. X#define PTRC(x) ((long) (char *) (x))
  85. X
  86. X#ifdef __STDC__
  87. Xextern char *sbrk(int);
  88. Xextern char *getenv(const char *);
  89. Xextern long strtol(const char *, char **, int);
  90. Xextern int kill(int, int);
  91. Xextern int getpid(void);
  92. Xextern int open(const char *, int, int);
  93. Xextern int write(int, const char *, int);
  94. X#else
  95. Xextern char *sbrk();
  96. Xextern char *getenv();
  97. Xextern long strtol();
  98. Xextern int kill();
  99. Xextern int getpid();
  100. Xextern int open();
  101. Xextern int write();
  102. X#endif
  103. Xextern char etext[];
  104. Xextern char edata[];
  105. Xextern char end[];
  106. X
  107. X#define SBRK_FAIL    ((char *) -1)
  108. X#define MAGIC_COOKIE    0xa5271009
  109. X#define FENCE_COOKIE    0xe4057492
  110. X#define ARR_BYTES    8
  111. X#define FENCE        (sizeof (long))
  112. X#define DPTR(blk)    ((char *) (blk)->m_blk)
  113. Xstatic long __f__;
  114. X#define BLKFENCE(blk)    \
  115. X    (memcpy((char *) &__f__, DPTR(blk) + (blk)->m_rsize, FENCE), __f__)
  116. X#define SET_BLKFENCE(b)    \
  117. X    (__f__=FENCE_COOKIE,memcpy(DPTR(blk)+(blk)->m_rsize,(char *)&__f__,FENCE))
  118. X#define BLKSIZE(blk)    \
  119. X    (PTRC(DPTR((struct _Dmi *) 0)) + ARR_BYTES + (blk)->m_size)
  120. X#define BLKEND(blk)    (DPTR(blk) + (blk)->m_size + ARR_BYTES)
  121. X#define NEWBLK(n)    (PTRC(DPTR((struct _Dmi *) 0)) + ARR_BYTES + (n))
  122. X#define m_round(n)    (((n) + ARR_BYTES - 1) & ~(ARR_BYTES - 1))
  123. X
  124. Xstruct _Dmi
  125. X{
  126. X    long m_cookie;
  127. X    struct _Dmi *m_next;
  128. X    struct _Dmi *m_prev;
  129. X    long m_size;
  130. X    long m_rsize;
  131. X    char m_blk[ARR_BYTES + FENCE];
  132. X};
  133. X
  134. X#define HEADSIZE    ((sizeof(struct _Dmi)) - ARR_BYTES)
  135. X
  136. Xstatic struct _Dmi *_fab = 0;
  137. Xstatic struct _Dmi *_ffb = 0;
  138. Xstatic char *_xbrk = 0;
  139. Xstatic long _in_malloc = 0;
  140. Xstatic long _no_memcpy = 0;
  141. Xstatic long _st_malloc = 0;
  142. Xlong _mall_opt = 0;
  143. Xstatic sighand_t old_bus = SIG_DFL;
  144. Xstatic sighand_t old_segv = SIG_DFL;
  145. Xstatic int _mall_fd = -1;
  146. X#ifdef MALLOC_TRACEBACK
  147. Xstatic int *_mall_frame;
  148. X#endif
  149. X
  150. Xstatic void _mallchk();
  151. Xstatic void _mallerr();
  152. X
  153. X/*
  154. X * internal: dump a string
  155. X */
  156. X
  157. Xstatic void
  158. X_mall_open()
  159. X{
  160. X    char buf[15];
  161. X    int c, old;
  162. X    char *cp;
  163. X
  164. X    if (_st_malloc != getpid())
  165. X    {
  166. X    close(_mall_fd);
  167. X    _mall_fd = -1;
  168. X    }
  169. X    if (_mall_fd == -1)
  170. X    {
  171. X    if (_st_malloc || !(cp = getenv("MALLOC_LOG")))
  172. X    {
  173. X        buf[0] = 'm', buf[1] = 'a', buf[2] = buf[3] = 'l', buf[4] = 'o';
  174. X        buf[5] = 'c', buf[6] = '.', buf[12] = '\0';
  175. X        _st_malloc = getpid();
  176. X        c = 11;
  177. X        while (_st_malloc && c > 6)
  178. X        {
  179. X        buf[c--] = _st_malloc % 10 + '0';
  180. X        _st_malloc /= 10;
  181. X        }
  182. X        cp = buf;
  183. X    }
  184. X    if ((_mall_fd = open(cp,O_WRONLY|O_CREAT|O_TRUNC|O_APPEND,0666)) == -1)
  185. X        _mall_fd = 2;
  186. X    else if (_mall_fd < 3)
  187. X    {
  188. X        old = _mall_fd;
  189. X        _mall_fd = fcntl(_mall_fd, F_DUPFD, 3);
  190. X        close(old);
  191. X    }
  192. X    }
  193. X}
  194. X
  195. Xstatic void
  196. X#ifdef __STDC__
  197. X_malldstr(const char *s)
  198. X#else
  199. X_malldstr(s)
  200. X    char *s;
  201. X#endif
  202. X{
  203. X    register long len;
  204. X
  205. X    _mall_open();
  206. X    for (len = 0; s[len]; len++)
  207. X    ;
  208. X    write(_mall_fd, s, len);
  209. X}
  210. X
  211. X/*
  212. X * internal: write a pointer in hex without using stdio
  213. X */
  214. X
  215. Xstatic void
  216. X#ifdef __STDC__
  217. X_malldptr(register unsigned long x)
  218. X#else
  219. X_malldptr(x)
  220. X    register unsigned long x;
  221. X#endif
  222. X{
  223. X    char buf[20];
  224. X    static const char hex[] = "0123456789abcdef";
  225. X    register unsigned long dx;
  226. X    register char *p;
  227. X
  228. X    _mall_open();
  229. X    if (!x)
  230. X    {
  231. X    write(_mall_fd, "0x0(0)", 6);
  232. X    return;
  233. X    }
  234. X    write(_mall_fd, "0x", 2);
  235. X    p = buf;
  236. X    dx = x;
  237. X    while (x != 0)
  238. X    *p++ = hex[x % 16], x = x / 16;
  239. X    while (p != buf)
  240. X    write(_mall_fd, --p, 1);
  241. X    write(_mall_fd, "(", 1);
  242. X    p = buf;
  243. X    x = dx;
  244. X    while (x != 0)
  245. X    *p++ = hex[x % 10], x /= 10;
  246. X    while (p != buf)
  247. X    write(_mall_fd, --p, 1);
  248. X    write(_mall_fd, ")", 1);
  249. X}
  250. X
  251. X#ifdef MALLOC_TRACEBACK
  252. X
  253. X/*
  254. X * This is EXTREMELY NON-PORTABLE but very useful.  I suggest you be familiar
  255. X * with debugger internals before hacking on this code.
  256. X */
  257. X
  258. Xstatic void
  259. X#ifdef __STDC__
  260. X_mall_chase(const int *stkptr)
  261. X#else
  262. X_mall_chase(stkptr)
  263. X    int *stkptr;
  264. X#endif
  265. X{
  266. X    _malldstr("traceback -\n");
  267. X    /*
  268. X     * We are given the address of an argument.  Treating it as a pointer to
  269. X     * an (int), we can then take ptr[-1] to get the caller's address.  To go
  270. X     * farther back, we must follow the stack frames.  Basically, a stack
  271. X     * frame looks like this, with descending addresses further in the list:
  272. X     *
  273. X     *    return address
  274. X     *    saved frame pointer (ebp of caller)
  275. X     *    local vars
  276. X     *    saved registers for local register vars
  277. X     *
  278. X     * (N.B.  This is for the i386/i486.  Your mileage WILL differ.)
  279. X     */
  280. X    if (stkptr < (int *) &stkptr || (char *) stkptr > MALLOC_LIMIT)
  281. X    {
  282. X    _mallerr("_mall_chase", "stack corrupted - frame got ",
  283. X         (long) stkptr);
  284. X    }
  285. X    while (*stkptr)
  286. X    {
  287. X    _malldstr("pc = ");
  288. X    _malldptr(*stkptr);
  289. X    _malldstr("\n");
  290. X    if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &stkptr ||
  291. X        (char *) stkptr > MALLOC_LIMIT)
  292. X    {
  293. X        _mallerr("_mall_chase", "stack corrupted - frame got ",
  294. X             (long) stkptr);
  295. X    }
  296. X    }
  297. X    _malldstr("end traceback\n");
  298. X}
  299. X
  300. X#endif
  301. X
  302. X/*
  303. X * dump arena; can be called externally, and is non-destructive
  304. X */
  305. X
  306. Xvoid
  307. X_malldmp()
  308. X{
  309. X    register struct _Dmi *blk;
  310. X    long oldf, oldm;
  311. X
  312. X    if ((oldf = _in_malloc))
  313. X    {
  314. X    _malldstr("malloc diagnostic dump\n");
  315. X#ifdef MALLOC_TRACEBACK
  316. X    _mall_chase(_mall_frame - 1);
  317. X#endif
  318. X    }
  319. X    _in_malloc = 0;
  320. X    oldm = _no_memcpy;
  321. X    _no_memcpy = 1;
  322. X    _malldstr("brk = ");
  323. X    _malldptr(PTRC(sbrk(0)));
  324. X    _malldstr("  xbrk = ");
  325. X    _malldptr(PTRC(_xbrk));
  326. X    _malldstr("\n_fab = ");
  327. X    _malldptr(PTRC(_fab));
  328. X    _malldstr("  _ffb = ");
  329. X    _malldptr(PTRC(_ffb));
  330. X    _malldstr("  blksiz = ");
  331. X    _malldptr(HEADSIZE);
  332. X    _malldstr("\netext = ");
  333. X    _malldptr(PTRC(etext));
  334. X    _malldstr("  edata = ");
  335. X    _malldptr(PTRC(edata));
  336. X    _malldstr("  end = ");
  337. X    _malldptr(PTRC(end));
  338. X    _malldstr("\n");
  339. X    if (!_fab)
  340. X    _malldstr("no allocated blocks\n");
  341. X    else
  342. X    {
  343. X    _malldstr("\nallocated blocks\n");
  344. X    for (blk = _fab;
  345. X         blk && PTRC(blk) >= PTRC(_xbrk) && PTRC(blk) < PTRC(sbrk(0));
  346. X         blk = blk->m_next)
  347. X    {
  348. X        _malldstr("(");
  349. X        _malldptr(PTRC(blk));
  350. X        _malldstr(") ");
  351. X        _malldptr(PTRC(blk->m_prev));
  352. X        _malldstr(" <");
  353. X        _malldptr(blk->m_rsize);
  354. X        _malldstr("/");
  355. X        _malldptr(blk->m_size);
  356. X        _malldstr("> ");
  357. X        _malldptr(PTRC(blk->m_next));
  358. X        if (MAGIC_COOKIE != blk->m_cookie)
  359. X        {
  360. X        _malldstr(" cookie==");
  361. X        _malldptr(blk->m_cookie);
  362. X        }
  363. X        if (FENCE_COOKIE != BLKFENCE(blk))
  364. X        {
  365. X        _malldstr(" fence==");
  366. X        _malldptr(BLKFENCE(blk));
  367. X        }
  368. X        _malldstr("\n");
  369. X    }
  370. X    if (blk)
  371. X        _malldstr("(subsequent block pointers corrupted)\n");
  372. X    }
  373. X    if (!_ffb)
  374. X    _malldstr("\nno free blocks\n");
  375. X    else
  376. X    {
  377. X    _malldstr("\nfree blocks\n");
  378. X    for (blk = _ffb;
  379. X         blk && PTRC(blk) >= PTRC(_xbrk) && PTRC(blk) < PTRC(sbrk(0));
  380. X         blk = blk->m_next)
  381. X    {
  382. X        _malldstr("(");
  383. X        _malldptr(PTRC(blk));
  384. X        _malldstr(")  ");
  385. X        _malldptr(PTRC(blk->m_prev));
  386. X        _malldstr("<  ");
  387. X        _malldptr(blk->m_size);
  388. X        _malldstr("  >");
  389. X        _malldptr(PTRC(blk->m_next));
  390. X        if (MAGIC_COOKIE != blk->m_cookie)
  391. X        {
  392. X        _malldstr("cookie==");
  393. X        _malldptr(blk->m_cookie);
  394. X        }
  395. X        _malldstr("\n");
  396. X    }
  397. X    if (blk)
  398. X        _malldstr("(subsequent block pointers corrupted)\n");
  399. X    }
  400. X    _no_memcpy = oldm;
  401. X    _in_malloc = oldf;
  402. X}
  403. X
  404. X/*
  405. X * internal error routine: print error message (without using stdio) and
  406. X * drop core
  407. X */
  408. X
  409. Xstatic void
  410. X#ifdef __STDC__
  411. X_mallerr(const char *fn, const char *s, long ptr)
  412. X#else
  413. X_mallerr(fn, s, ptr)
  414. X    char *fn, *s;
  415. X    long ptr;
  416. X#endif
  417. X{
  418. X    _malldstr(fn);
  419. X    _malldstr(": ");
  420. X    _malldstr(s);
  421. X    _malldptr(ptr);
  422. X    _malldstr("\n");
  423. X    _malldmp();
  424. X    signal(SIGQUIT, SIG_DFL);
  425. X    kill(getpid(), SIGQUIT);
  426. X}
  427. X
  428. X/*
  429. X * initialize stuff, we want to _malldmp() on a bus/seg error
  430. X */
  431. X
  432. Xstatic void
  433. X#ifdef __STDC__
  434. X_mall_sig(int sig)
  435. X#else
  436. X_mall_sig(sig)
  437. X    int sig;
  438. X#endif
  439. X{
  440. X    if (sig == SIGSEGV)
  441. X    {
  442. X    _malldstr("\nsegmentation violation\n\n");
  443. X    signal(SIGSEGV, old_segv);
  444. X    }
  445. X    else if (sig == SIGBUS)
  446. X    {
  447. X    _malldstr("\nbus error\n\n");
  448. X    signal(SIGBUS, old_bus);
  449. X    }
  450. X    else if (sig == SIGSYS)
  451. X    _malldstr("\ninvalid argument\n\n");
  452. X    else {
  453. X    _malldstr("\nsignal ");
  454. X    _malldptr(sig);
  455. X    _malldstr("\n\n");
  456. X    }
  457. X#ifdef MALLOC_TRACEBACK
  458. X    _mall_chase((int *) &sig - 1);
  459. X#endif
  460. X    _in_malloc = 1;        /* silence _mallchk's default header */
  461. X    _mallchk("signal trap");
  462. X    kill(getpid(), sig);
  463. X}
  464. X
  465. Xstatic void
  466. X_mall_init()
  467. X{
  468. X    const char *cp;
  469. X    sighand_t tmp;
  470. X
  471. X    if (_mall_opt & _MALL_SEGV)
  472. X    {
  473. X    tmp = old_segv;
  474. X    if ((old_segv = signal(SIGSEGV, _mall_sig)) == _mall_sig)
  475. X        old_segv = tmp;
  476. X    }
  477. X    if (_mall_opt & _MALL_BUS)
  478. X    {
  479. X    tmp = old_bus;
  480. X    if ((old_bus = signal(SIGBUS, _mall_sig)) == _mall_sig)
  481. X        old_bus = tmp;
  482. X    }
  483. X    if (_st_malloc)
  484. X    return;
  485. X    _mall_opt = MALLOC_DEFAULT;
  486. X    if ((cp = getenv("MALLOC_OPTS")))
  487. X    {
  488. X    while (*cp)
  489. X    {
  490. X        switch (*cp)
  491. X        {
  492. X        case 'v':
  493. X        _mall_opt ^= _MALL_VFUNC;
  494. X        break;
  495. X#ifdef MALLOC_TRACEBACK
  496. X        case 't':
  497. X        _mall_opt ^= _MALL_TFUNC;
  498. X        break;
  499. X#endif
  500. X#ifdef MALLOC_LIB
  501. X        case 'V':
  502. X        _mall_opt ^= _MALL_VUTIL;
  503. X        break;
  504. X#ifdef MALLOC_TRACEBACK
  505. X        case 'T':
  506. X        _mall_opt ^= _MALL_TUTIL;
  507. X        break;
  508. X#endif
  509. X#endif
  510. X        case 'm':
  511. X        _mall_opt ^= _MALL_MALLOC_0;
  512. X        break;
  513. X        case 'b':
  514. X        _mall_opt ^= _MALL_VBLK;
  515. X        break;
  516. X        case 'f':
  517. X        _mall_opt ^= _MALL_FREE_0;
  518. X        break;
  519. X        case 'u':
  520. X        _mall_opt ^= _MALL_UNBREAK;
  521. X        break;
  522. X        case 'r':
  523. X        _mall_opt ^= _MALL_REALLOC_0;
  524. X        break;
  525. X        case 'S':
  526. X        if ((_mall_opt ^= _MALL_SEGV) & _MALL_SEGV)
  527. X        {
  528. X            tmp = old_segv;
  529. X            if ((old_segv = signal(SIGSEGV, _mall_sig))
  530. X            == _mall_sig)
  531. X            old_segv = tmp;
  532. X        }
  533. X        else
  534. X        {
  535. X            if ((tmp = signal(SIGSEGV, old_segv)) != _mall_sig)
  536. X            signal(SIGSEGV, tmp);
  537. X        }
  538. X        break;
  539. X        case 'B':
  540. X        if ((_mall_opt ^= _MALL_BUS) & _MALL_BUS)
  541. X        {
  542. X            tmp = old_bus;
  543. X            if ((old_bus = signal(SIGBUS, _mall_sig)) == _mall_sig)
  544. X            old_bus = tmp;
  545. X        }
  546. X        else
  547. X        {
  548. X            if ((tmp = signal(SIGBUS, old_bus)) != _mall_sig)
  549. X            signal(SIGBUS, tmp);
  550. X        }
  551. X        break;
  552. X        default:
  553. X        break;
  554. X        }
  555. X        cp++;
  556. X    }
  557. X    }
  558. X    _st_malloc = getpid();
  559. X}
  560. X
  561. X/*
  562. X * figure out which allocation block this pointer came from
  563. X * return NULL if none
  564. X */
  565. X
  566. Xstatic struct _Dmi *
  567. X#ifdef __STDC__
  568. X_mallgb(const char *s)
  569. X#else
  570. X_mallgb(s)
  571. X    char *s;
  572. X#endif
  573. X{
  574. X    register struct _Dmi *blk;
  575. X
  576. X    for (blk = _fab; blk; blk = blk->m_next)
  577. X    {
  578. X    if (blk->m_blk == s)
  579. X        break;
  580. X    }
  581. X    return blk;
  582. X}
  583. X
  584. X/*
  585. X * _mallchk() is global, so external routines can do discreet checks on the
  586. X * arena.  If the arena is detectably corrupted, it will abort().
  587. X */
  588. X
  589. Xvoid
  590. X#ifdef __STDC__
  591. X_mallchk(const char *fn)
  592. X#else
  593. X_mallchk(fn)
  594. X    char *fn;
  595. X#endif
  596. X{
  597. X    register struct _Dmi *blk, *cblk;
  598. X    register char *send;
  599. X    register long cnt;
  600. X    long oldm;
  601. X#ifdef MALLOC_TRACEBACK
  602. X    int *stkptr;
  603. X#endif
  604. X
  605. X    if (!_in_malloc && (_mall_opt & _MALL_VFUNC))
  606. X    {
  607. X    _malldstr("called _mallchk(");
  608. X    _malldptr((long) fn);
  609. X    _malldstr(")\n");
  610. X#ifdef MALLOC_TRACEBACK
  611. X    if (_mall_opt & _MALL_TFUNC)
  612. X        _mall_chase((int *) &fn - 1);
  613. X#endif
  614. X    }
  615. X    oldm = _no_memcpy;
  616. X    _no_memcpy = 1;
  617. X#ifdef MALLOC_TRACEBACK
  618. X    if ((stkptr = (int *) &fn - 1) < (int *) &stkptr ||
  619. X    (char *) stkptr > MALLOC_LIMIT)
  620. X    {
  621. X    _mallerr("mallchk", "stack corrupted - frame got ", (long) stkptr);
  622. X    }
  623. X    while (*stkptr)
  624. X    {
  625. X    if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &stkptr ||
  626. X        (char *) stkptr > MALLOC_LIMIT)
  627. X    {
  628. X        _mallerr("mallchk", "stack corrupted - frame got ", (long) stkptr);
  629. X    }
  630. X    }
  631. X#endif
  632. X    send = sbrk(0);
  633. X    cblk = 0;
  634. X    for (blk = _fab; blk; cblk = blk, blk = blk->m_next)
  635. X    {
  636. X    if (PTRC(blk) < PTRC(_xbrk) || PTRC(blk) >= PTRC(send))
  637. X    {
  638. X        _mallerr(fn, "allocated block list corrupted: blkptr = ",
  639. X             (long) blk);
  640. X    }
  641. X    if (blk->m_cookie != MAGIC_COOKIE)
  642. X    {
  643. X        _mallerr(fn, "allocated block list corrupted, bad magic cookie: ",
  644. X             blk->m_cookie);
  645. X    }
  646. X    if (blk->m_prev != cblk)
  647. X    {
  648. X        _mallerr(fn, "allocated block list corrupted: bad backptr blk ",
  649. X             (long) blk);
  650. X    }
  651. X    if (blk->m_size < 0)
  652. X    {
  653. X        _mallerr(fn, "allocated block list corrupted: blk->m_size = ",
  654. X             blk->m_size);
  655. X    }
  656. X    if (blk->m_rsize < 0)
  657. X    {
  658. X        _mallerr(fn, "allocated block list corrupted: blk->m_rsize = ",
  659. X             blk->m_rsize);
  660. X    }
  661. X    /* one for this block, one for the failed potential next block */
  662. X    if (blk->m_rsize <= blk->m_size - 2 * NEWBLK(ARR_BYTES))
  663. X    {
  664. X        _mallerr(fn, "allocated block list corrupted: rsize too small = ",
  665. X             blk->m_rsize);
  666. X    }
  667. X    if (blk->m_rsize > blk->m_size)
  668. X    {
  669. X        _mallerr(fn, "allocated block list corrupted: rsize too big = ",
  670. X             blk->m_rsize);
  671. X    }
  672. X    if (BLKFENCE(blk) != FENCE_COOKIE)
  673. X    {
  674. X        _mallerr(fn, "allocated block list corrupted, bad fence cookie: ",
  675. X             BLKFENCE(blk));
  676. X    }
  677. X    }
  678. X    cblk = 0;
  679. X    for (blk = _ffb; blk; cblk = blk, blk = blk->m_next)
  680. X    {
  681. X    if (PTRC(blk) < PTRC(_xbrk) || PTRC(blk) >= PTRC(send))
  682. X        _mallerr(fn, "free block list corrupted: blkptr = ", (long) blk);
  683. X    if (blk->m_cookie != MAGIC_COOKIE)
  684. X    {
  685. X        _mallerr(fn, "free block list corrupted, bad magic cookie",
  686. X             blk->m_cookie);
  687. X    }
  688. X    if (blk->m_prev != cblk)
  689. X    {
  690. X        _mallerr(fn, "free block list corrupted: bad backptr blk ",
  691. X             (long) blk);
  692. X    }
  693. X    if (blk->m_size < 0)
  694. X    {
  695. X        _mallerr(fn, "free block list corrupted: blk->m_size = ",
  696. X             blk->m_size);
  697. X    }
  698. X    }
  699. X    for (blk = _fab; blk; blk = blk->m_next)
  700. X    {
  701. X    if ((long) BLKEND(blk) > PTRC(send))
  702. X    {
  703. X        _malldstr("(brk = ");
  704. X        _malldptr(PTRC(send));
  705. X        _malldstr(", eblk = ");
  706. X        _malldptr((long) BLKEND(blk));
  707. X        _malldstr(")\n");
  708. X        _mallerr(fn, "allocated block extends past brk: ", (long) blk);
  709. X    }
  710. X    cnt = 0;
  711. X    for (cblk = _fab; cblk; cblk = cblk->m_next)
  712. X    {
  713. X        if (blk == cblk)
  714. X        {
  715. X        if (!cnt++)
  716. X            continue;
  717. X        _mallerr(fn, "block allocated twice: ", (long) blk);
  718. X        }
  719. X        if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
  720. X        {
  721. X        _malldstr("(blk = ");
  722. X        _malldptr(PTRC(blk));
  723. X        _malldstr(", cblk = ");
  724. X        _malldptr(PTRC(cblk));
  725. X        _malldstr(")\n");
  726. X        _mallerr(fn, "nested block in allocated list: ", (long) blk);
  727. X        }
  728. X    }
  729. X    for (cblk = _ffb; cblk; cblk = cblk->m_next)
  730. X    {
  731. X        if (blk == cblk)
  732. X        {
  733. X        _mallerr(fn, "block on allocated and free lists: ",
  734. X             (long) blk);
  735. X        }
  736. X        if (PTRC(blk) > PTRC(cblk) && PTRC(blk) < (long) BLKEND(cblk))
  737. X        {
  738. X        _malldstr("(blk = ");
  739. X        _malldptr(PTRC(blk));
  740. X        _malldstr(", cblk = ");
  741. X        _malldptr(PTRC(cblk));
  742. X        _malldstr(", ecblk = ");
  743. X        _malldptr(PTRC(BLKEND(cblk)));
  744. X        _malldstr(")\n");
  745. X        _mallerr(fn, "alloced block nested in free block: ",
  746. X             (long) blk);
  747. X        }
  748. X    }
  749. X    }
  750. X    for (blk = _ffb; blk; blk = blk->m_next)
  751. X    {
  752. X    if ((long) BLKEND(blk) > PTRC(send))
  753. X    {
  754. X        _malldstr("(brk = ");
  755. X        _malldptr(PTRC(send));
  756. X        _malldstr(", eblk = ");
  757. X        _malldptr((long) BLKEND(blk));
  758. X        _malldstr(")\n");
  759. X        _mallerr(fn, "free block extends past brk: ", (long) blk);
  760. X    }
  761. X    cnt = 0;
  762. X    for (cblk = _ffb; cblk; cblk = cblk->m_next)
  763. X    {
  764. X        if (blk == cblk)
  765. X        {
  766. X        if (!cnt++)
  767. X            continue;
  768. X        _mallerr(fn, "block freed twice: ", (long) blk);
  769. X        }
  770. X        if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
  771. X        {
  772. X        _malldstr("(blk = ");
  773. X        _malldptr(PTRC(blk));
  774. X        _malldstr(", cblk = ");
  775. X        _malldptr(PTRC(cblk));
  776. X        _malldstr(")\n");
  777. X        _mallerr(fn, "nested block in free list: ", (long) blk);
  778. X        }
  779. X    }
  780. X    for (cblk = _fab; cblk; cblk = cblk->m_next)
  781. X    {
  782. X        if (blk == cblk)
  783. X        {
  784. X        _mallerr(fn, "block on allocated and free lists: ",
  785. X             (long) blk);
  786. X        }
  787. X        if (blk > cblk && PTRC(blk) < (long) BLKEND(cblk))
  788. X        {
  789. X        _malldstr("(blk = ");
  790. X        _malldptr(PTRC(blk));
  791. X        _malldstr(", cblk = ");
  792. X        _malldptr(PTRC(cblk));
  793. X        _malldstr(")\n");
  794. X        _mallerr(fn, "free block nested in alloced block: ",
  795. X             (long) blk);
  796. X        }
  797. X    }
  798. X    }
  799. X    _no_memcpy = oldm;
  800. X}
  801. X    
  802. Xchar *
  803. X#ifdef __STDC__
  804. Xmalloc(unsigned int size)
  805. X#else
  806. Xmalloc(size)
  807. X    unsigned int size;
  808. X#endif
  809. X{
  810. X    register struct _Dmi *blk;
  811. X    register unsigned int n;
  812. X
  813. X#ifdef MALLOC_TRACEBACK
  814. X    if (!_in_malloc)
  815. X    _mall_frame = (int *) &size;
  816. X#endif
  817. X    n = m_round(size);
  818. X    _in_malloc = 1;
  819. X    _mall_init();
  820. X    if (_mall_opt & _MALL_VFUNC)
  821. X    {
  822. X    _malldstr("called malloc(");
  823. X    _malldptr(size);
  824. X    _malldstr(")\n");
  825. X#ifdef MALLOC_TRACEBACK
  826. X    if (_mall_opt & _MALL_TFUNC)
  827. X        _mall_chase(((int *) &size) - 1);
  828. X#endif
  829. X    }
  830. X    _mallchk("malloc");
  831. X    if (!size)
  832. X    {
  833. X    if (_mall_opt & _MALL_MALLOC_0)
  834. X        _malldstr("warning: malloc(0) is unsafe\n");
  835. X    else
  836. X    {
  837. X        _malldstr("malloc(0) is illegal\n");
  838. X        _mall_sig(SIGSYS);
  839. X    }
  840. X    }
  841. X    for (blk = _ffb; blk; blk = blk->m_next)
  842. X    {
  843. X    if (blk->m_size >= n)
  844. X    {
  845. X        /* split a large block to save memory and enable some checking */
  846. X        if (blk->m_size >= n + NEWBLK(ARR_BYTES))
  847. X        {
  848. X        blk->m_size -= n + NEWBLK(ARR_BYTES);
  849. X        ((char *) blk) += BLKSIZE(blk);
  850. X        blk->m_cookie = MAGIC_COOKIE;
  851. X        blk->m_size = n;
  852. X        }
  853. X        else
  854. X        {
  855. X        if (blk->m_next)
  856. X            blk->m_next->m_prev = blk->m_prev;
  857. X        if (blk->m_prev)
  858. X            blk->m_prev->m_next = blk->m_next;
  859. X        if (blk == _ffb)
  860. X            _ffb = blk->m_next;
  861. X        }
  862. X        blk->m_next = _fab;
  863. X        blk->m_prev = 0;
  864. X        blk->m_rsize = size;
  865. X        SET_BLKFENCE(blk);
  866. X        if (_fab)
  867. X        _fab->m_prev = blk;
  868. X        _fab = blk;
  869. X        _in_malloc = 0;
  870. X        if (_mall_opt & _MALL_VBLK)
  871. X        {
  872. X        _malldstr("returned block ");
  873. X        _malldptr((long) blk);
  874. X        _malldstr(" user ptr ");
  875. X        _malldptr((long) blk->m_blk);
  876. X        _malldstr("\n");
  877. X        }
  878. X        return blk->m_blk;
  879. X    }
  880. X    }
  881. X    if ((char *) (blk = (struct _Dmi *) sbrk(NEWBLK(n))) == SBRK_FAIL)
  882. X    {
  883. X    _in_malloc = 0;
  884. X    if (_mall_opt & _MALL_VBLK)
  885. X    {
  886. X        _malldstr("returned failure\n");
  887. X    }
  888. X    return 0;    /* no space */
  889. X    }
  890. X    if (!_xbrk)
  891. X    _xbrk = (char *) blk;
  892. X    blk->m_next = _fab;
  893. X    blk->m_prev = 0;
  894. X    blk->m_cookie = MAGIC_COOKIE;
  895. X    blk->m_size = n;
  896. X    blk->m_rsize = size;
  897. X    SET_BLKFENCE(blk);
  898. X    if (_fab)
  899. X    _fab->m_prev = blk;
  900. X    _fab = blk;
  901. X    _in_malloc = 0;
  902. X    if (_mall_opt & _MALL_VBLK)
  903. X    {
  904. X    _malldstr("returned block ");
  905. X    _malldptr((long) blk);
  906. X    _malldstr(" user ptr ");
  907. X    _malldptr((long) blk->m_blk);
  908. X    _malldstr("\n");
  909. X    }
  910. X    return blk->m_blk;
  911. X}
  912. X
  913. Xvoid
  914. X#ifdef __STDC__
  915. Xfree(char *s)
  916. X#else
  917. Xfree(s)
  918. X    char *s;
  919. X#endif
  920. X{
  921. X    register struct _Dmi *blk, *fblk, *cblk;
  922. X    int didit;
  923. X
  924. X#ifdef MALLOC_TRACEBACK
  925. X    if (!_in_malloc)
  926. X    _mall_frame = (int *) &s;
  927. X#endif
  928. X    _in_malloc = 1;
  929. X    _mall_init();
  930. X    if (_mall_opt & _MALL_VFUNC)
  931. X    {
  932. X    _malldstr("called free(");
  933. X    _malldptr(PTRC(s));
  934. X    _malldstr(")\n");
  935. X#ifdef MALLOC_TRACEBACK
  936. X    if (_mall_opt & _MALL_TFUNC)
  937. X        _mall_chase(((int *) &s) - 1);
  938. X#endif
  939. X    }
  940. X    _mallchk("free");
  941. X    if (!s)
  942. X    {
  943. X    if (_mall_opt & _MALL_FREE_0)
  944. X    {
  945. X        _malldstr("warning: free(0) is unsafe\n");
  946. X        _in_malloc = 0;
  947. X        return;
  948. X    }
  949. X    else
  950. X    {
  951. X        _malldstr("free(0) is illegal\n");
  952. X        _mall_sig(SIGSYS);
  953. X    }
  954. X    }
  955. X    if (!(blk = _mallgb(s)))
  956. X    _mallerr("non-allocated pointer passed to free(): ", s, 0);
  957. X    if (blk->m_prev)
  958. X    blk->m_prev->m_next = blk->m_next;
  959. X    if (blk->m_next)
  960. X    blk->m_next->m_prev = blk->m_prev;
  961. X    if (blk == _fab)
  962. X    _fab = blk->m_next;
  963. X    blk->m_prev = 0;
  964. X    blk->m_next = _ffb;
  965. X    if (_ffb)
  966. X    _ffb->m_prev = blk;
  967. X    _ffb = blk;
  968. X/*
  969. X * crunch the free list by coalescing consecutive free blocks
  970. X */
  971. X    didit = 1;
  972. X    while (didit)
  973. X    {
  974. X    didit = 0;
  975. X    for (fblk = _ffb; fblk; fblk = fblk->m_next)
  976. X    {
  977. X        for (cblk = _ffb; cblk; cblk = cblk->m_next)
  978. X        {
  979. X        if (cblk == fblk)
  980. X            continue;
  981. X        if (PTRC(fblk) + BLKSIZE(fblk) == PTRC(cblk))
  982. X        {
  983. X            fblk->m_size += BLKSIZE(cblk);
  984. X            if (cblk->m_prev)
  985. X            cblk->m_prev->m_next = cblk->m_next;
  986. X            if (cblk->m_next)
  987. X            cblk->m_next->m_prev = cblk->m_prev;
  988. X            if (_ffb == cblk)
  989. X            _ffb = cblk->m_next;
  990. X            didit = 1;
  991. X            fblk = 0;
  992. X            break;
  993. X        }
  994. X        }
  995. X        if (!fblk)
  996. X        break;    /* force a recycle, since we zapped the chain */
  997. X    }
  998. X    }
  999. X    if (!(_mall_opt & _MALL_UNBREAK))
  1000. X    {
  1001. X    _in_malloc = 0;
  1002. X    return;
  1003. X    }
  1004. X    for (fblk = _ffb; fblk; fblk = fblk->m_next)
  1005. X    {
  1006. X    if ((long) BLKEND(fblk) == PTRC(sbrk(0)))
  1007. X    {
  1008. X        if (fblk->m_next)
  1009. X        fblk->m_next->m_prev = fblk->m_prev;
  1010. X        if (fblk->m_prev)
  1011. X        fblk->m_prev->m_next = fblk->m_next;
  1012. X        if (fblk == _ffb)
  1013. X        _ffb = fblk->m_next;
  1014. X        sbrk(- fblk->m_size);
  1015. X        break;        /* this can only happen once */
  1016. X    }
  1017. X    }
  1018. X    _in_malloc = 0;
  1019. X}
  1020. X
  1021. Xchar *
  1022. X#ifdef __STDC__
  1023. Xrealloc(char *s, unsigned int size)
  1024. X#else
  1025. Xrealloc(s, size)
  1026. X    char *s;
  1027. X    unsigned int size;
  1028. X#endif
  1029. X{
  1030. X    register char *s1, *d, *d1;
  1031. X    register struct _Dmi *blk;
  1032. X
  1033. X    if (_mall_opt & _MALL_VFUNC)
  1034. X    {
  1035. X    _malldstr("called realloc(");
  1036. X    _malldptr(PTRC(s));
  1037. X    _malldstr(", ");
  1038. X    _malldptr(size);
  1039. X    _malldstr(")\n");
  1040. X#ifdef MALLOC_TRACEBACK
  1041. X    if (_mall_opt & _MALL_TFUNC)
  1042. X        _mall_chase(((int *) &s) - 1);
  1043. X#endif
  1044. X    }
  1045. X    _mallchk("realloc");
  1046. X    if (!s)
  1047. X    {
  1048. X    if (_mall_opt & _MALL_REALLOC_0)
  1049. X    {
  1050. X        _malldstr("warning: realloc(0, size) is unsafe\n");
  1051. X        return malloc(size);
  1052. X    }
  1053. X    else
  1054. X    {
  1055. X        _malldstr("realloc(0, size) is illegal\n");
  1056. X        _mall_sig(SIGSYS);
  1057. X    }
  1058. X    }
  1059. X    if (!size)
  1060. X    {
  1061. X    if (_mall_opt & _MALL_REALLOC_0)
  1062. X        _malldstr("warning: realloc(ptr, 0) is unsafe\n");
  1063. X    else
  1064. X    {
  1065. X        _malldstr("realloc(ptr, 0) is illegal\n");
  1066. X        _mall_sig(SIGSYS);
  1067. X    }
  1068. X    }
  1069. X    if (!(blk = _mallgb(s)))
  1070. X    {
  1071. X    _mallerr("realloc", "non-allocated pointer passed to realloc(): ",
  1072. X         (long) s);
  1073. X    }
  1074. X    if (!(s1 = malloc(size)))
  1075. X    return 0;
  1076. X    if (blk->m_size < size)
  1077. X    size = blk->m_size;
  1078. X    d1 = s1;
  1079. X    d = s;
  1080. X    while (size--)
  1081. X    *((char *) d1)++ = *((char *) d)++;
  1082. X    free(s);
  1083. X    return s1;
  1084. X}
  1085. X
  1086. X/*
  1087. X * malloc objects and zero storage
  1088. X */
  1089. X
  1090. Xchar *
  1091. X#ifdef __STDC__
  1092. Xcalloc(unsigned int n, unsigned int size)
  1093. X#else
  1094. Xcalloc(n, size)
  1095. X    unsigned int n, size;
  1096. X#endif
  1097. X{
  1098. X    register char *s, *s1;
  1099. X
  1100. X    if (_mall_opt & _MALL_VFUNC)
  1101. X    {
  1102. X    _malldstr("called calloc(");
  1103. X    _malldptr(n);
  1104. X    _malldstr(", ");
  1105. X    _malldptr(size);
  1106. X    _malldstr(")\n");
  1107. X#ifdef MALLOC_TRACEBACK
  1108. X    if (_mall_opt & _MALL_TFUNC)
  1109. X        _mall_chase(((int *) &n) - 1);
  1110. X#endif
  1111. X    }
  1112. X    n *= size;
  1113. X    if (!(s = malloc(n)))
  1114. X    return 0;
  1115. X    for (s1 = s; n; n--)
  1116. X    *((char *) s1)++ = '\0';
  1117. X    return s;
  1118. X}
  1119. X
  1120. X/*
  1121. X * for some reason this is in /lib/libc.a(calloc.o)
  1122. X */
  1123. X
  1124. Xvoid
  1125. X#ifdef __STDC__
  1126. Xcfree(char *s)
  1127. X#else
  1128. Xcfree(s)
  1129. X    char *s;
  1130. X#endif
  1131. X{
  1132. X    free(s);
  1133. X}
  1134. X
  1135. X#ifdef MALLOC_LIB
  1136. X
  1137. X/*
  1138. X * Reimplementations of some library functions that often take malloc'ed
  1139. X * pointers as arguments.  The idea is that we can head off a sizeable number
  1140. X * of potential disasters before they happen, and hopefully pinpoint the
  1141. X * location of a bug a little more closely than the next operation that uses
  1142. X * malloc (or dumps core...).
  1143. X */
  1144. X
  1145. Xlong
  1146. X#ifdef __STDC__
  1147. X_mallpchk(const char *c)
  1148. X#else
  1149. X_mallpchk(c)
  1150. X    char *c;
  1151. X#endif
  1152. X{
  1153. X    struct _Dmi *d;        /* I'd like this to be register, but... */
  1154. X
  1155. X    if (!_in_malloc && (_mall_opt & _MALL_VFUNC))
  1156. X    {
  1157. X    _malldstr("called _mallpchk(");
  1158. X    _malldptr((long) c);
  1159. X    _malldstr(")\n");
  1160. X#ifdef MALLOC_TRACEBACK
  1161. X    if (_mall_opt & _MALL_TFUNC)
  1162. X        _mall_chase((int *) &c - 1);
  1163. X#endif
  1164. X    }
  1165. X    if (c == 0)
  1166. X    {
  1167. X    _malldstr("mallpchk(");
  1168. X    _malldptr((long) c);
  1169. X    _malldstr(") null\n");
  1170. X    return -1;
  1171. X    }
  1172. X    /*
  1173. X     * Theory:  things shouldn't stomp on segments they don't belong to.
  1174. X     * After all, how often does a data segment variable extend into bss?
  1175. X     */
  1176. X    if (c < etext)
  1177. X    return (long) etext - (long) c;
  1178. X    if (c < edata)
  1179. X    return (long) edata - (long) c;
  1180. X    if (c < end)
  1181. X    return (long) end - (long) c;
  1182. X    if (c < _xbrk)
  1183. X    return (long) _xbrk - (long) c;
  1184. X    if (c >= sbrk(0) && c < (char *) &d)
  1185. X    {
  1186. X    _malldstr("mallpchk(");
  1187. X    _malldptr((long) c);
  1188. X    _malldstr(") ptr outside brk\n");
  1189. X    return -1;
  1190. X    }
  1191. X    if (c >= (char *) &d && c <= MALLOC_LIMIT)
  1192. X    {
  1193. X#ifndef MALLOC_TRACEBACK
  1194. X    return (long) MALLOC_LIMIT - (long) c;
  1195. X#else
  1196. X    int *stkptr;
  1197. X
  1198. X    if ((stkptr = (int *) &c - 1) < (int *) &d ||
  1199. X        (char *) stkptr > MALLOC_LIMIT)
  1200. X    {
  1201. X        _mallerr("mallpchk", "stack corrupted - frame got ",
  1202. X             (long) stkptr);
  1203. X    }
  1204. X    while (*stkptr)
  1205. X    {
  1206. X        if ((long) c >= (long) stkptr && (long) c < stkptr[-1])
  1207. X        return (long) c + (long) stkptr - stkptr[-1] - 1;
  1208. X        if ((stkptr = (int *) stkptr[-1] + 1) < (int *) &d ||
  1209. X        (char *) stkptr > MALLOC_LIMIT)
  1210. X        {
  1211. X        _mallerr("mallpchk", "stack corrupted - frame got ",
  1212. X             (long) stkptr);
  1213. X        }
  1214. X    }
  1215. X    if (c > (char *) stkptr)        /* environ[] or argv[] */
  1216. X        return MALLOC_LIMIT - (char *) stkptr;
  1217. X    _malldstr("mallpchk(");
  1218. X    _malldptr((long) c);
  1219. X    _malldstr(") stack is damaged\n");
  1220. X    return -1;
  1221. X#endif
  1222. X    }
  1223. X    if (c >= MALLOC_LIMIT)
  1224. X    {
  1225. X    _malldstr("mallpchk(");
  1226. X    _malldptr((long) c);
  1227. X    _malldstr(") ptr outside address space\n");
  1228. X    return -1;
  1229. X    }
  1230. X    for (d = _fab; d; d = d->m_next)
  1231. X    {
  1232. X    if (c >= d->m_blk && c < d->m_blk + d->m_size)
  1233. X        return d->m_size + (long) d->m_blk - (long) c;
  1234. X    }
  1235. X    _malldstr("mallpchk(");
  1236. X    _malldptr((long) c);
  1237. X    _malldstr(") found no valid block\n");
  1238. X    _malldmp();
  1239. X    return -1;
  1240. X}
  1241. X
  1242. Xchar *
  1243. X#ifdef __STDC__
  1244. Xstrcpy(char *d, const char *s)
  1245. X#else
  1246. Xstrcpy(d, s)
  1247. X    char *d, *s;
  1248. X#endif
  1249. X{
  1250. X    register int c;
  1251. X    int l, m;
  1252. X
  1253. X    _mall_init();
  1254. X    _in_malloc = 1;
  1255. X#ifdef MALLOC_TRACEBACK
  1256. X    _mall_frame = (int *) &d;
  1257. X#endif
  1258. X    if (_mall_opt & _MALL_VUTIL)
  1259. X    {
  1260. X    _malldstr("called strcpy(");
  1261. X    _malldptr((long) d);
  1262. X    _malldstr(", ");
  1263. X    _malldptr((long) s);
  1264. X    _malldstr(")\n");
  1265. X#ifdef MALLOC_TRACEBACK
  1266. X    if (_mall_opt & _MALL_TUTIL)
  1267. X        _mall_chase(((int *) &d) - 1);
  1268. X#endif
  1269. X    }
  1270. X    _mallchk("strcpy");
  1271. X    if (!d)
  1272. X    {
  1273. X    _malldstr("strcpy to null pointer\n");
  1274. X    _mall_sig(SIGSYS);
  1275. X    }
  1276. X    if (!s)
  1277. X    {
  1278. X    _malldstr("strcpy from null pointer\n");
  1279. X    _mall_sig(SIGSYS);
  1280. X    }
  1281. X    if ((m = _mallpchk(d)) < 0)
  1282. X    {
  1283. X    _malldstr("strcpy to invalid addr ");
  1284. X    _malldptr((long) d);
  1285. X    _malldstr("\n");
  1286. X    _mall_sig(SIGSYS);
  1287. X    }
  1288. X    if ((l = _mallpchk(s)) < 0)
  1289. X    {
  1290. X    _malldstr("strcpy from invalid addr ");
  1291. X    _malldptr((long) s);
  1292. X    _malldstr("\n");
  1293. X    _mall_sig(SIGSYS);
  1294. X    }
  1295. X    for (c = 0; s[c]; c++)
  1296. X    {
  1297. X    if (c == l)
  1298. X    {
  1299. X        _malldstr("strcpy src ");
  1300. X        _malldptr((long) s);
  1301. X        _malldstr(" too long\n");
  1302. X        _mall_sig(SIGSYS);
  1303. X    }
  1304. X    if (c == m)
  1305. X    {
  1306. X        _malldstr("strcpy dest ");
  1307. X        _malldptr((long) d);
  1308. X        _malldstr(" too short\n");
  1309. X        _mall_sig(SIGSYS);
  1310. X    }
  1311. X    d[c] = s[c];
  1312. X    }
  1313. X    if (c == m)
  1314. X    {
  1315. X    _malldstr("strcpy dest ");
  1316. X    _malldptr((long) d);
  1317. X    _malldstr(" too short\n");
  1318. X    _mall_sig(SIGSYS);
  1319. X    }
  1320. X    d[c] = 0;
  1321. X    _in_malloc = 0;
  1322. X    return d;
  1323. X}
  1324. X
  1325. Xchar *
  1326. X#ifdef __STDC__
  1327. Xstrncpy(char *d, const char *s, int n)
  1328. X#else
  1329. Xstrncpy(d, s, n)
  1330. X    char *d, *s;
  1331. X    int n;
  1332. X#endif
  1333. X{
  1334. X    register int c;
  1335. X    int l, m;
  1336. X
  1337. X    _mall_init();
  1338. X    _in_malloc = 1;
  1339. X#ifdef MALLOC_TRACEBACK
  1340. X    _mall_frame = (int *) &d;
  1341. X#endif
  1342. X    if (_mall_opt & _MALL_VUTIL)
  1343. X    {
  1344. X    _malldstr("called strncpy(");
  1345. X    _malldptr((long) d);
  1346. X    _malldstr(", ");
  1347. X    _malldptr((long) s);
  1348. X    _malldstr(", ");
  1349. X    _malldptr(n);
  1350. X    _malldstr(")\n");
  1351. X#ifdef MALLOC_TRACEBACK
  1352. X    if (_mall_opt & _MALL_TUTIL)
  1353. X        _mall_chase(((int *) &d) - 1);
  1354. X#endif
  1355. X    }
  1356. X    _mallchk("strncpy");
  1357. X    if (!d)
  1358. X    {
  1359. X    _malldstr("strncpy to null pointer\n");
  1360. X    _mall_sig(SIGSYS);
  1361. X    }
  1362. X    if (!s)
  1363. X    {
  1364. X    _malldstr("strncpy from null pointer\n");
  1365. X    _mall_sig(SIGSYS);
  1366. X    }
  1367. X    if (n < 0)
  1368. X    {
  1369. X    _malldstr("strncpy(dest, src, ");
  1370. X    _malldptr(n);
  1371. X    _malldstr(") negative count\n");
  1372. X    _mall_sig(SIGSYS);
  1373. X    }
  1374. X    if ((m = _mallpchk(d)) < 0)
  1375. X    {
  1376. X    _malldstr("strncpy to invalid addr ");
  1377. X    _malldptr((long) d);
  1378. X    _malldstr("\n");
  1379. X    _mall_sig(SIGSYS);
  1380. X    }
  1381. X    if (m < n)
  1382. X    {
  1383. X    _malldstr("strncpy dest ");
  1384. X    _malldptr((long) d);
  1385. X    _malldstr(" too short\n");
  1386. X    _mall_sig(SIGSYS);
  1387. X    }
  1388. X    if ((l = _mallpchk(s)) < 0)
  1389. X    {
  1390. X    _malldstr("strncpy from invalid addr ");
  1391. X    _malldptr((long) s);
  1392. X    _malldstr("\n");
  1393. X    _mall_sig(SIGSYS);
  1394. X    }
  1395. X    for (c = 0; s[c] && n--; c++)
  1396. X    {
  1397. X    if (c == l)
  1398. X    {
  1399. X        _malldstr("strncpy src ");
  1400. X        _malldptr((long) s);
  1401. X        _malldstr(" too long\n");
  1402. X        _mall_sig(SIGSYS);
  1403. X    }
  1404. X    d[c] = s[c];
  1405. X    }
  1406. X    while (n--)
  1407. X    d[c++] = 0;
  1408. X    _in_malloc = 0;
  1409. X    return d;
  1410. X}
  1411. X
  1412. Xchar *
  1413. X#ifdef __STDC__
  1414. Xstrcat(char *d, const char *s)
  1415. X#else
  1416. Xstrcat(d, s)
  1417. X    char *d, *s;
  1418. X#endif
  1419. X{
  1420. X    register int c, a;
  1421. X    int l, m;
  1422. X
  1423. X    _mall_init();
  1424. X    _in_malloc = 1;
  1425. X#ifdef MALLOC_TRACEBACK
  1426. X    _mall_frame = (int *) &d;
  1427. X#endif
  1428. X    if (_mall_opt & _MALL_VUTIL)
  1429. X    {
  1430. X    _malldstr("called strcat(");
  1431. X    _malldptr((long) d);
  1432. X    _malldstr(", ");
  1433. X    _malldptr((long) s);
  1434. X    _malldstr(")\n");
  1435. X#ifdef MALLOC_TRACEBACK
  1436. X    if (_mall_opt & _MALL_TUTIL)
  1437. X        _mall_chase(((int *) &d) - 1);
  1438. X#endif
  1439. X    }
  1440. X    _mallchk("strcat");
  1441. X    if (!d)
  1442. X    {
  1443. X    _malldstr("strcat to null pointer\n");
  1444. X    _mall_sig(SIGSYS);
  1445. X    }
  1446. X    if (!s)
  1447. X    {
  1448. X    _malldstr("strcat from null pointer\n");
  1449. X    _mall_sig(SIGSYS);
  1450. X    }
  1451. X    if ((m = _mallpchk(d)) < 0)
  1452. X    {
  1453. X    _malldstr("strcat to invalid addr ");
  1454. X    _malldptr((long) d);
  1455. X    _malldstr("\n");
  1456. X    _mall_sig(SIGSYS);
  1457. X    }
  1458. X    if ((l = _mallpchk(s)) < 0)
  1459. X    {
  1460. X    _malldstr("strcat from invalid addr ");
  1461. X    _malldptr((long) s);
  1462. X    _malldstr("\n");
  1463. X    _mall_sig(SIGSYS);
  1464. X    }
  1465. X    for (a = 0; a < m && d[a]; a++)
  1466. X    ;
  1467. X    if (a == m)
  1468. X    {
  1469. X    _malldstr("strcat dest ");
  1470. X    _malldptr((long) d);
  1471. X    _malldstr(" too short\n");
  1472. X    _mall_sig(SIGSYS);
  1473. X    }
  1474. X    for (c = 0; s[c]; c++)
  1475. X    {
  1476. X    if (c == l)
  1477. X    {
  1478. X        _malldstr("strcat src ");
  1479. X        _malldptr((long) s);
  1480. X        _malldstr(" too long\n");
  1481. X        _mall_sig(SIGSYS);
  1482. X    }
  1483. X    if (c + a == m)
  1484. X    {
  1485. X        _malldstr("strcat dest ");
  1486. X        _malldptr((long) d);
  1487. X        _malldstr(" too short\n");
  1488. X        _mall_sig(SIGSYS);
  1489. X    }
  1490. X    d[c + a] = s[c];
  1491. X    }
  1492. X    if (c + a == m)
  1493. X    {
  1494. X    _malldstr("strcat dest ");
  1495. X    _malldptr((long) d);
  1496. X    _malldstr(" too short\n");
  1497. X    _mall_sig(SIGSYS);
  1498. X    }
  1499. X    d[c + a] = 0;
  1500. X    _in_malloc = 0;
  1501. X    return d;
  1502. X}
  1503. X
  1504. Xchar *
  1505. X#ifdef __STDC__
  1506. Xstrncat(char *d, const char *s, int n)
  1507. X#else
  1508. Xstrncat(d, s, n)
  1509. X    char *d, *s;
  1510. X    int n;
  1511. X#endif
  1512. X{
  1513. X    register int c, a;
  1514. X    int l, m;
  1515. X
  1516. X    _mall_init();
  1517. X    _in_malloc = 1;
  1518. X#ifdef MALLOC_TRACEBACK
  1519. X    _mall_frame = (int *) &d;
  1520. X#endif
  1521. X    if (_mall_opt & _MALL_VUTIL)
  1522. X    {
  1523. X    _malldstr("called strncat(");
  1524. X    _malldptr((long) d);
  1525. X    _malldstr(", ");
  1526. X    _malldptr((long) s);
  1527. X    _malldstr(", ");
  1528. X    _malldptr(n);
  1529. X    _malldstr(")\n");
  1530. X#ifdef MALLOC_TRACEBACK
  1531. X    if (_mall_opt & _MALL_TUTIL)
  1532. X        _mall_chase(((int *) &d) - 1);
  1533. X#endif
  1534. X    }
  1535. X    _mallchk("strncat");
  1536. X    if (!d)
  1537. X    {
  1538. X    _malldstr("strncat to null pointer\n");
  1539. X    _mall_sig(SIGSYS);
  1540. X    }
  1541. X    if (!s)
  1542. X    {
  1543. X    _malldstr("strncat from null pointer\n");
  1544. X    _mall_sig(SIGSYS);
  1545. X    }
  1546. X    if (n < 0)
  1547. X    {
  1548. X    _malldstr("strncat(dest, src, ");
  1549. X    _malldptr(n);
  1550. X    _malldstr(") negative count\n");
  1551. X    _mall_sig(SIGSYS);
  1552. X    }
  1553. X    if ((m = _mallpchk(d)) < 0)
  1554. X    {
  1555. X    _malldstr("strncat to invalid addr ");
  1556. X    _malldptr((long) d);
  1557. X    _malldstr("\n");
  1558. X    _mall_sig(SIGSYS);
  1559. X    }
  1560. X    for (a = 0; a < m && d[a]; a++)
  1561. X    ;
  1562. X    if (a + n > m)
  1563. X    {
  1564. X    _malldstr("strncat dest ");
  1565. X    _malldptr((long) d);
  1566. X    _malldstr(" too short\n");
  1567. X    _mall_sig(SIGSYS);
  1568. X    }
  1569. X    if ((l = _mallpchk(s)) < 0)
  1570. X    {
  1571. X    _malldstr("strncat from invalid addr ");
  1572. X    _malldptr((long) s);
  1573. X    _malldstr("\n");
  1574. X    _mall_sig(SIGSYS);
  1575. X    }
  1576. X    for (c = 0; s[c] && n--; c++)
  1577. X    {
  1578. X    if (c == l)
  1579. X    {
  1580. X        _malldstr("strncat src ");
  1581. X        _malldptr((long) s);
  1582. X        _malldstr(" too long\n");
  1583. X        _mall_sig(SIGSYS);
  1584. X    }
  1585. X    d[c + a] = s[c];
  1586. X    }
  1587. X    while (n--)
  1588. X    d[c++ + a] = 0;
  1589. X    _in_malloc = 0;
  1590. X    return d;
  1591. X}
  1592. X
  1593. Xchar *
  1594. X#ifdef __STDC__
  1595. Xmemcpy(char *d, const char *s, int n)
  1596. X#else
  1597. Xmemcpy(d, s, n)
  1598. X    char *d, *s;
  1599. X    int n;
  1600. X#endif
  1601. X{
  1602. X    register int c;
  1603. X    int l, m, o;
  1604. X
  1605. X    if (!(o = _in_malloc) && !_no_memcpy)
  1606. X    {
  1607. X    _mall_init();
  1608. X    _in_malloc = 1;
  1609. X#ifdef MALLOC_TRACEBACK
  1610. X    _mall_frame = (int *) &d;
  1611. X#endif
  1612. X    if (_mall_opt & _MALL_VUTIL)
  1613. X    {
  1614. X        _malldstr("called memcpy(");
  1615. X        _malldptr((long) d);
  1616. X        _malldstr(", ");
  1617. X        _malldptr((long) s);
  1618. X        _malldstr(", ");
  1619. X        _malldptr(n);
  1620. X        _malldstr(")\n");
  1621. X#ifdef MALLOC_TRACEBACK
  1622. X        if (_mall_opt & _MALL_TUTIL)
  1623. X        _mall_chase(((int *) &d) - 1);
  1624. X#endif
  1625. X    }
  1626. X    _mallchk("memcpy");
  1627. X    if (!d)
  1628. X    {
  1629. X        _malldstr("memcpy to null pointer\n");
  1630. X        _mall_sig(SIGSYS);
  1631. X    }
  1632. X    if (!s)
  1633. X    {
  1634. X        _malldstr("memcpy from null pointer\n");
  1635. X        _mall_sig(SIGSYS);
  1636. X    }
  1637. X    if (n < 0)
  1638. X    {
  1639. X        _malldstr("memcpy(dest, src, ");
  1640. X        _malldptr(n);
  1641. X        _malldstr(") negative count\n");
  1642. X        _mall_sig(SIGSYS);
  1643. X    }
  1644. X    if ((m = _mallpchk(d)) < 0)
  1645. X    {
  1646. X        _malldstr("memcpy to invalid addr ");
  1647. X        _malldptr((long) d);
  1648. X        _malldstr("\n");
  1649. X        _mall_sig(SIGSYS);
  1650. X    }
  1651. X    if (m < n)
  1652. X    {
  1653. X        _malldstr("memcpy dest ");
  1654. X        _malldptr((long) d);
  1655. X        _malldstr(" too short\n");
  1656. X        _mall_sig(SIGSYS);
  1657. X    }
  1658. X    if ((l = _mallpchk(s)) < 0)
  1659. X    {
  1660. X        _malldstr("memcpy from invalid addr ");
  1661. X        _malldptr((long) s);
  1662. X        _malldstr("\n");
  1663. X        _mall_sig(SIGSYS);
  1664. X    }
  1665. X    if (l < n)
  1666. X    {
  1667. X        _malldstr("memcpy src ");
  1668. X        _malldptr((long) s);
  1669. X        _malldstr(" too short\n");
  1670. X        _mall_sig(SIGSYS);
  1671. X    }
  1672. X    }
  1673. X    for (c = 0; n--; c++)
  1674. X    d[c] = s[c];
  1675. X    _in_malloc = o;
  1676. X    return d;
  1677. X}
  1678. X
  1679. Xchar *
  1680. X#ifdef __STDC__
  1681. Xmemset(char *d, int s, int n)
  1682. X#else
  1683. Xmemset(d, s, n)
  1684. X    char *d;
  1685. X    int s, n;
  1686. X#endif
  1687. X{
  1688. X    register int c;
  1689. X    int m;
  1690. X
  1691. X    _mall_init();
  1692. X    _in_malloc = 1;
  1693. X#ifdef MALLOC_TRACEBACK
  1694. X    _mall_frame = (int *) &s;
  1695. X#endif
  1696. X    if (_mall_opt & _MALL_VUTIL)
  1697. X    {
  1698. X    _malldstr("called memset(");
  1699. X    _malldptr((long) d);
  1700. X    _malldstr(", ");
  1701. X    _malldptr(s);
  1702. X    _malldstr(", ");
  1703. X    _malldptr(n);
  1704. X    _malldstr(")\n");
  1705. X#ifdef MALLOC_TRACEBACK
  1706. X    if (_mall_opt & _MALL_TUTIL)
  1707. X        _mall_chase(((int *) &d) - 1);
  1708. X#endif
  1709. X    }
  1710. X    _mallchk("memset");
  1711. X    if (!d)
  1712. X    {
  1713. X    _malldstr("memset to null pointer\n");
  1714. X    _mall_sig(SIGSYS);
  1715. X    }
  1716. X    if (n < 0)
  1717. X    {
  1718. X    _malldstr("memset(dest, src, ");
  1719. X    _malldptr(n);
  1720. X    _malldstr(") negative count\n");
  1721. X    _mall_sig(SIGSYS);
  1722. X    }
  1723. X    if ((m = _mallpchk(d)) < 0)
  1724. X    {
  1725. X    _malldstr("memset to invalid addr ");
  1726. X    _malldptr((long) d);
  1727. X    _malldstr("\n");
  1728. X    _mall_sig(SIGSYS);
  1729. X    }
  1730. X    if (m < n)
  1731. X    {
  1732. X    _malldstr("memset dest ");
  1733. X    _malldptr((long) d);
  1734. X    _malldstr(" too short\n");
  1735. X    _mall_sig(SIGSYS);
  1736. X    }
  1737. X    for (c = 0; n--; c++)
  1738. X    d[c] = s;
  1739. X    _in_malloc = 0;
  1740. X    return d;
  1741. X}
  1742. X
  1743. X/*
  1744. X * Validate a STDIO pointer.  User-invoked diagnostic routine, I am not
  1745. X * going to rewrite stdio just to do pointer checks!
  1746. X */
  1747. X
  1748. X#include <stdio.h>
  1749. X
  1750. Xvoid
  1751. X_mallschk(fp)
  1752. X    FILE *fp;
  1753. X{
  1754. X    if (_mall_opt & _MALL_VFUNC)
  1755. X    {
  1756. X    _malldstr("called _mallschk(");
  1757. X    _malldptr((long) fp);
  1758. X    _malldstr(")\n");
  1759. X#ifdef MALLOC_TRACEBACK
  1760. X    if (_mall_opt & _MALL_TFUNC)
  1761. X        _mall_chase((int *) &fp - 1);
  1762. X#endif
  1763. X    }
  1764. X    _in_malloc = 1;
  1765. X    if (_mallpchk((char *) fp) == -1)
  1766. X    _mallerr("mallschk", "stdio FILE * out of range", (long) fp);
  1767. X    _malldstr("stdio ptr ");
  1768. X    _malldptr((long) fp);
  1769. X    _malldstr(" {ptr=");
  1770. X    _malldptr((long) fp->_ptr);
  1771. X    _malldstr(", cnt=");
  1772. X    _malldptr((long) fp->_cnt);
  1773. X    _malldstr(", base=");
  1774. X    _malldptr((long) fp->_base);
  1775. X    _malldstr(", bufend=");
  1776. X    _malldptr((long) _bufend(fp));
  1777. X    _malldstr(", file=");
  1778. X    _malldptr((long) fp->_file);
  1779. X    _malldstr(", flag=");
  1780. X    _malldptr((long) fp->_flag);
  1781. X    _malldstr("}\n");
  1782. X    if (_mallpchk((char *) fp->_ptr) == -1)
  1783. X    _mallerr("mallschk", "stdio buf ptr out of range", (long) fp->_ptr);
  1784. X    if (_mallpchk((char *) fp->_base) == -1)
  1785. X    _mallerr("mallschk", "stdio base ptr out of range", (long) fp->_base);
  1786. X    if (_mallpchk((char *) _bufend(fp)) == -1)
  1787. X    {
  1788. X    _mallerr("mallschk", "stdio bufend ptr out of range",
  1789. X         (long) _bufend(fp));
  1790. X    }
  1791. X    if (fp->_base + fp->_cnt >= _bufend(fp))
  1792. X    _mallerr("mallschk", "stdio bufcnt out of range", fp->_cnt);
  1793. X    _in_malloc = 0;
  1794. X}
  1795. X
  1796. X#endif
  1797. ________This_Is_The_END________
  1798. echo 'x - malloc.h'
  1799. sed 's/^X//' <<'________This_Is_The_END________' >>malloc.h
  1800. X/*
  1801. X * malloc for debugging -- allocates via sbrk and tracks stuff, does diag dump
  1802. X * if things appear to be screwed up.                    (bsa)
  1803. X */
  1804. X
  1805. X#if defined(__STDC__)
  1806. Xextern void _malldmp(void);
  1807. Xextern char *malloc(unsigned int);
  1808. Xextern void free(char *);
  1809. Xextern char *realloc(char *, unsigned int);
  1810. Xextern void _mallchk(const char *);
  1811. Xextern char *calloc(unsigned int, unsigned int);
  1812. Xextern void cfree(char *);
  1813. Xextern char *strcpy(char *, const char *);
  1814. Xextern char *strncpy(char *, const char *, int);
  1815. Xextern char *strcat(char *, const char *);
  1816. Xextern char *strncat(char *, const char *, int);
  1817. Xextern char *memcpy(char *, const char *, int);
  1818. Xextern char *memset(char *, int, int);
  1819. X#else
  1820. Xextern void _malldmp();
  1821. Xextern char *malloc();
  1822. Xextern void free();
  1823. Xextern char *realloc();
  1824. Xextern void _mallchk();
  1825. Xextern char *calloc();
  1826. Xextern void cfree();
  1827. Xextern char *strcpy();
  1828. Xextern char *strncpy();
  1829. Xextern char *strcat();
  1830. Xextern char *strncat();
  1831. Xextern char *memcpy();
  1832. Xextern char *memset();
  1833. X#endif
  1834. X
  1835. X#define _MALL_VFUNC    0x00000001    /* v */
  1836. X#define _MALL_TFUNC    0x00000002    /* t */
  1837. X#define _MALL_VUTIL    0x00000004    /* V */
  1838. X#define _MALL_TUTIL    0x00000008    /* T */
  1839. X#define _MALL_MALLOC_0    0x00000010    /* m */
  1840. X#define _MALL_VBLK    0x00000020    /* b */
  1841. X#define _MALL_FREE_0    0x00000040    /* f */
  1842. X#define _MALL_UNBREAK    0x00000080    /* u */
  1843. X#define _MALL_REALLOC_0    0x00000100    /* r */
  1844. X#define _MALL_SEGV    0x00000200    /* S */
  1845. X#define _MALL_BUS    0x00000400    /* B */
  1846. ________This_Is_The_END________
  1847. echo 'x - malltest.c'
  1848. sed 's/^X//' <<'________This_Is_The_END________' >>malltest.c
  1849. X#include <stdio.h>
  1850. X
  1851. Xextern void setbuf();
  1852. Xextern char *strrchr();
  1853. Xextern char *malloc();
  1854. Xextern char *realloc();
  1855. Xextern void free();
  1856. Xextern int getopt();
  1857. Xextern void exit();
  1858. Xextern void srand48();
  1859. Xextern double drand48();
  1860. Xextern long time();
  1861. Xextern int getpid();
  1862. Xextern int printf();
  1863. Xextern int fprintf();
  1864. Xextern long strtol();
  1865. X
  1866. Xextern char *optarg;
  1867. Xextern int optind;
  1868. X
  1869. Xint
  1870. Xrnd(l, h)
  1871. X    int l, h;
  1872. X{
  1873. X    static int initialized = 0;
  1874. X
  1875. X    if (l == h)
  1876. X    return l;
  1877. X    if (!initialized)
  1878. X    {
  1879. X    srand48(getpid() ^ time((long *) 0));
  1880. X    initialized = 1;
  1881. X    }
  1882. X    return (int) (drand48() * (h - l + 1) + l);
  1883. X}
  1884. X
  1885. Xint
  1886. Xmain(argc, argv)
  1887. X    int argc;
  1888. X    char **argv;
  1889. X{
  1890. X    char **allocs;
  1891. X    int cnt, opt, repeats, low, high, errs, slots;
  1892. X    char *myname, *cp;
  1893. X    
  1894. X    setbuf(stderr, (char *) 0);
  1895. X    if ((myname = strrchr(argv[0], '/')))
  1896. X    myname++;
  1897. X    else
  1898. X    myname = argv[0];
  1899. X    repeats = 1;
  1900. X    slots = 100;
  1901. X    low = 1;
  1902. X    high = 32768;
  1903. X    while ((opt = getopt(argc, argv, "r:l:h:s:")) != EOF)
  1904. X    {
  1905. X    switch (opt)
  1906. X    {
  1907. X    case 'r':
  1908. X        cnt = strtol(optarg, &cp, 0);
  1909. X        if (cp == optarg || *cp)
  1910. X        {
  1911. X        fprintf(stderr, "%s: invalid number \"%s\" for -r\n", myname,
  1912. X            optarg);
  1913. X        errs++;
  1914. X        }
  1915. X        else if (cnt <= 0)
  1916. X        {
  1917. X        fprintf(stderr, "%s: -r repeat count must be positive\n",
  1918. X            myname);
  1919. X        errs++;
  1920. X        }
  1921. X        else
  1922. X        repeats = cnt;
  1923. X        break;
  1924. X    case 'l':
  1925. X        cnt = strtol(optarg, &cp, 0);
  1926. X        if (cp == optarg || *cp)
  1927. X        {
  1928. X        fprintf(stderr, "%s: invalid number \"%s\" for -l\n", myname,
  1929. X            optarg);
  1930. X        errs++;
  1931. X        }
  1932. X        else if (cnt <= 0)
  1933. X        {
  1934. X        fprintf(stderr, "%s: -l lower limit must be positive\n",
  1935. X            myname);
  1936. X        errs++;
  1937. X        }
  1938. X        else
  1939. X        low = cnt;
  1940. X        break;
  1941. X    case 'h':
  1942. X        cnt = strtol(optarg, &cp, 0);
  1943. X        if (cp == optarg || *cp)
  1944. X        {
  1945. X        fprintf(stderr, "%s: invalid number \"%s\" for -h\n", myname,
  1946. X            optarg);
  1947. X        errs++;
  1948. X        }
  1949. X        else if (cnt <= 0)
  1950. X        {
  1951. X        fprintf(stderr, "%s: -h higher limit must be positive\n",
  1952. X            myname);
  1953. X        errs++;
  1954. X        }
  1955. X        else
  1956. X        high = cnt;
  1957. X        break;
  1958. X    case 's':
  1959. X        cnt = strtol(optarg, &cp, 0);
  1960. X        if (cp == optarg || *cp)
  1961. X        {
  1962. X        fprintf(stderr, "%s: invalid number \"%s\" for -s\n", myname,
  1963. X            optarg);
  1964. X        errs++;
  1965. X        }
  1966. X        else if (cnt <= 0)
  1967. X        {
  1968. X        fprintf(stderr, "%s: -s slot count must be positive\n",
  1969. X            myname);
  1970. X        errs++;
  1971. X        }
  1972. X        else
  1973. X        slots = cnt;
  1974. X        break;
  1975. X    default:
  1976. X        errs++;
  1977. X        break;
  1978. X    }
  1979. X    }
  1980. X    if (errs)
  1981. X    {
  1982. X    fprintf(stderr,
  1983. X        "usage: malloc_test [-r repeat] [-l lowlim] [-h highlim]\n");
  1984. X    exit(1);
  1985. X    }
  1986. X    while (repeats--)
  1987. X    {
  1988. X    if (!(allocs = (char **) malloc(slots * sizeof *allocs)))
  1989. X    {
  1990. X        fprintf(stderr, "%s: can't allocate %d slots\n", myname, slots);
  1991. X        exit(1);
  1992. X    }
  1993. X    for (cnt = 0; cnt < slots; cnt++)
  1994. X    {
  1995. X        if (!(allocs[cnt] = malloc(errs = rnd(low, high))))
  1996. X        {
  1997. X        fprintf(stderr, "%s: can't allocate %d bytes for slot %d\n",
  1998. X            myname, errs, cnt);
  1999. X        exit(1);
  2000. X        }
  2001. X    }
  2002. X    for (cnt = 0; cnt < slots; cnt++)
  2003. X    {
  2004. X        if (!(allocs[cnt] = realloc(allocs[cnt], errs = rnd(low, high))))
  2005. X        {
  2006. X        fprintf(stderr, "%s: can't reallocate %d bytes for slot %d\n",
  2007. X            myname, errs, cnt);
  2008. X        exit(1);
  2009. X        }
  2010. X    }
  2011. X    for (cnt = 0; cnt < slots; cnt++)
  2012. X        free(allocs[cnt]);
  2013. X    free(allocs);
  2014. X    }
  2015. X    printf("%s: test completed successfully\n", myname);
  2016. X    return 0;
  2017. X}
  2018. ________This_Is_The_END________
  2019. exit
  2020. -- 
  2021. Me: Brandon S. Allbery             KF8NH: DC to LIGHT!  [44.70.4.88]
  2022. Internet: allbery@NCoast.ORG         Delphi: ALLBERY
  2023. uunet!usenet.ins.cwru.edu!ncoast!allbery
  2024.  
  2025. exit 0 # Just in case...
  2026.