If freedynamicdata() gets called twice, for whatever reason, a "double free" can occur. warning: 44 ./nptl/pthread_kill.c: No such file or directory (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x00007ffff7c8b26e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x00007ffff7c6e8ff in __GI_abort () at ./stdlib/abort.c:79 #5 0x00007ffff7c6f7b6 in __libc_message_impl (fmt=fmt@entry=0x7ffff7e148d7 "%s\n") at ../sysdeps/posix/libc_fatal.c:132 #6 0x00007ffff7ceefe5 in malloc_printerr (str=str@entry=0x7ffff7e17bf0 "free(): double free detected in tcache 2") at ./malloc/malloc.c:5772 #7 0x00007ffff7cf154f in _int_free (av=0x7ffff7e49ac0 <main_arena>, p=<optimized out>, have_lock=0) at ./malloc/malloc.c:4541 #8 0x00007ffff7cf3d9e in __GI___libc_free (mem=0x555555ad82a0) at ./malloc/malloc.c:3398 #9 0x00005555557c12e9 in free_rect () at rect.c:48 #10 0x00005555557d77a2 in freedynamicdata () at save.c:1240 #11 0x0000555555682754 in nh_terminate (status=0) at end.c:1671 #12 0x000055555589af15 in opt_terminate () at ../sys/unix/unixmain.c:768 #13 0x000055555589af7a in after_opt_showpaths (dir=0x0) at ../sys/unix/unixmain.c:796 #14 0x0000555555693dd9 in do_deferred_showpaths (code=0) at files.c:4491 #15 0x0000555555778405 in initoptions () at options.c:6948 #16 0x0000555555899cd9 in main (argc=2, argv=0x7fffffffdad8) at ../sys/unix/unixmain.c:151
220 lines
4.5 KiB
C
220 lines
4.5 KiB
C
/* NetHack 3.7 rect.c $NHDT-Date: 1596498203 2020/08/03 23:43:23 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.14 $ */
|
|
/* Copyright (c) 1990 by Jean-Christophe Collet */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "hack.h"
|
|
|
|
int get_rect_ind(NhRect *);
|
|
|
|
staticfn boolean intersect(NhRect *, NhRect *, NhRect *);
|
|
|
|
/*
|
|
* In this file, we will handle the various rectangle functions we
|
|
* need for room generation.
|
|
*/
|
|
|
|
#define XLIM 4
|
|
#define YLIM 3
|
|
|
|
static NhRect *rect = (NhRect *) 0;
|
|
static int n_rects = 0;
|
|
static int rect_cnt;
|
|
|
|
/*
|
|
* Initialization of internal structures. Should be called for every
|
|
* new level to be build...
|
|
*/
|
|
|
|
void
|
|
init_rect(void)
|
|
{
|
|
if (!rect) {
|
|
n_rects = (COLNO * ROWNO) / 30;
|
|
rect = (NhRect *) alloc(sizeof(NhRect) * n_rects);
|
|
if (!rect)
|
|
panic("Could not alloc rect");
|
|
}
|
|
|
|
rect_cnt = 1;
|
|
rect[0].lx = rect[0].ly = 0;
|
|
rect[0].hx = COLNO - 1;
|
|
rect[0].hy = ROWNO - 1;
|
|
}
|
|
|
|
void
|
|
free_rect(void)
|
|
{
|
|
if (rect)
|
|
free(rect);
|
|
rect = 0;
|
|
n_rects = rect_cnt = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* Search Index of one precise NhRect.
|
|
*
|
|
*/
|
|
|
|
int
|
|
get_rect_ind(NhRect *r)
|
|
{
|
|
NhRect *rectp;
|
|
int lx, ly, hx, hy;
|
|
int i;
|
|
|
|
lx = r->lx;
|
|
ly = r->ly;
|
|
hx = r->hx;
|
|
hy = r->hy;
|
|
for (i = 0, rectp = &rect[0]; i < rect_cnt; i++, rectp++)
|
|
if (lx == rectp->lx && ly == rectp->ly && hx == rectp->hx
|
|
&& hy == rectp->hy)
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Search a free rectangle that include the one given in arg
|
|
*/
|
|
|
|
NhRect *
|
|
get_rect(NhRect *r)
|
|
{
|
|
NhRect *rectp;
|
|
int lx, ly, hx, hy;
|
|
int i;
|
|
|
|
lx = r->lx;
|
|
ly = r->ly;
|
|
hx = r->hx;
|
|
hy = r->hy;
|
|
for (i = 0, rectp = &rect[0]; i < rect_cnt; i++, rectp++)
|
|
if (lx >= rectp->lx && ly >= rectp->ly && hx <= rectp->hx
|
|
&& hy <= rectp->hy)
|
|
return rectp;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Get some random NhRect from the list.
|
|
*/
|
|
|
|
NhRect *
|
|
rnd_rect(void)
|
|
{
|
|
return rect_cnt > 0 ? &rect[rn2(rect_cnt)] : 0;
|
|
}
|
|
|
|
/*
|
|
* Search intersection between two rectangles (r1 & r2).
|
|
* return TRUE if intersection exist and put it in r3.
|
|
* otherwise returns FALSE
|
|
*/
|
|
|
|
staticfn boolean
|
|
intersect(NhRect *r1, NhRect *r2, NhRect *r3)
|
|
{
|
|
if (r2->lx > r1->hx || r2->ly > r1->hy || r2->hx < r1->lx
|
|
|| r2->hy < r1->ly)
|
|
return FALSE;
|
|
|
|
r3->lx = (r2->lx > r1->lx ? r2->lx : r1->lx);
|
|
r3->ly = (r2->ly > r1->ly ? r2->ly : r1->ly);
|
|
r3->hx = (r2->hx > r1->hx ? r1->hx : r2->hx);
|
|
r3->hy = (r2->hy > r1->hy ? r1->hy : r2->hy);
|
|
|
|
if (r3->lx > r3->hx || r3->ly > r3->hy)
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
/* Put the rectangle containing both r1 and r2 into r3 */
|
|
void
|
|
rect_bounds(NhRect r1, NhRect r2, NhRect *r3)
|
|
{
|
|
r3->lx = min(r1.lx, r2.lx);
|
|
r3->ly = min(r1.ly, r2.ly);
|
|
r3->hx = max(r1.hx, r2.hx);
|
|
r3->hy = max(r1.hy, r2.hy);
|
|
}
|
|
|
|
/*
|
|
* Remove a rectangle from the list of free NhRect.
|
|
*/
|
|
|
|
void
|
|
remove_rect(NhRect *r)
|
|
{
|
|
int ind;
|
|
|
|
ind = get_rect_ind(r);
|
|
if (ind >= 0)
|
|
rect[ind] = rect[--rect_cnt];
|
|
}
|
|
|
|
/*
|
|
* Add a NhRect to the list.
|
|
*/
|
|
|
|
void
|
|
add_rect(NhRect *r)
|
|
{
|
|
if (rect_cnt >= n_rects) {
|
|
impossible("n_rects may be too small.");
|
|
return;
|
|
}
|
|
/* Check that this NhRect is not included in another one */
|
|
if (get_rect(r))
|
|
return;
|
|
rect[rect_cnt] = *r;
|
|
rect_cnt++;
|
|
}
|
|
|
|
/*
|
|
* Okay, here we have two rectangles (r1 & r2).
|
|
* r1 was already in the list and r2 is included in r1.
|
|
* What we want is to allocate r2, that is split r1 into smaller rectangles
|
|
* then remove it.
|
|
*/
|
|
|
|
void
|
|
split_rects(NhRect *r1, NhRect *r2)
|
|
{
|
|
NhRect r, old_r;
|
|
int i;
|
|
|
|
old_r = *r1;
|
|
remove_rect(r1);
|
|
|
|
/* Walk down since rect_cnt & rect[] will change... */
|
|
for (i = rect_cnt - 1; i >= 0; i--)
|
|
if (intersect(&rect[i], r2, &r))
|
|
split_rects(&rect[i], &r);
|
|
|
|
if (r2->ly - old_r.ly - 1
|
|
> (old_r.hy < ROWNO - 1 ? 2 * YLIM : YLIM + 1) + 4) {
|
|
r = old_r;
|
|
r.hy = r2->ly - 2;
|
|
add_rect(&r);
|
|
}
|
|
if (r2->lx - old_r.lx - 1
|
|
> (old_r.hx < COLNO - 1 ? 2 * XLIM : XLIM + 1) + 4) {
|
|
r = old_r;
|
|
r.hx = r2->lx - 2;
|
|
add_rect(&r);
|
|
}
|
|
if (old_r.hy - r2->hy - 1 > (old_r.ly > 0 ? 2 * YLIM : YLIM + 1) + 4) {
|
|
r = old_r;
|
|
r.ly = r2->hy + 2;
|
|
add_rect(&r);
|
|
}
|
|
if (old_r.hx - r2->hx - 1 > (old_r.lx > 0 ? 2 * XLIM : XLIM + 1) + 4) {
|
|
r = old_r;
|
|
r.lx = r2->hx + 2;
|
|
add_rect(&r);
|
|
}
|
|
}
|
|
|
|
/*rect.c*/
|