summaryrefslogtreecommitdiff
path: root/system/pdksh/patches/011_OpenBSD-alloc.patch
blob: ec272897e2bb1f126c4bb4a5731cb393893e3755 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    + alloc.c: Kill hand-made memory allocation code, that is definitely
      buggy. Replace with simple wrapper around malloc, at least this works,
      and it's easier to debug anyways.
    + alloc.c: Don't allow alloc() and aresize() to fail.  Their return 
      value was only checked in two place (both in conjunction with 
      str_save).  Upon malloc/realloc failure we call internal_errorf()
      which pops throws and error and pops back to the last good state.	
Index: pdksh-5.2.14/alloc.c
===================================================================
--- pdksh-5.2.14.orig/alloc.c	2008-04-15 20:46:56.000000000 +0200
+++ pdksh-5.2.14/alloc.c	2008-04-15 20:50:18.000000000 +0200
@@ -1,3 +1,5 @@
+#ifndef DEBIAN
+
 /*
  * area-based allocation built on malloc/free
  */
@@ -110,6 +112,13 @@
 	Block  *block;
 	struct {int _;} junk;	/* alignment */
 	double djunk;		/* alignment */
+#ifdef DEBIAN /* patch from RedHat */
+#ifdef __ia64__
+       /* IA64 requires 16 byte alignment for some objects, so make
+        * this the minimum allocation size */
+	char    ajunk[16];
+#endif
+#endif
 };
 
 struct Block {
@@ -282,7 +291,9 @@
 	 * working (as it assumes size < ICELLS means it is not
 	 * a `large object').
 	 */
-	if (oldcells > ICELLS && cells > ICELLS) {
+	if (oldcells > ICELLS && cells > ICELLS
+	    && ((dp-2)->block->last == dp+oldcells) /* don't destroy blocks which have grown! */
+	   ) {
 		Block *bp = (dp-2)->block;
 		Block *nbp;
 		/* Saved in case realloc fails.. */
@@ -332,7 +343,7 @@
 	 * (need to check that cells < ICELLS so we don't make an
 	 * object a `large' - that would mess everything up).
 	 */
-	if (dp && cells > oldcells && cells <= ICELLS) {
+	if (dp && cells > oldcells) {
 		Cell *fp, *fpp;
 		Block *bp = (dp-2)->block;
 		int need = cells - oldcells - NOBJECT_FIELDS;
@@ -363,7 +374,7 @@
 	 * it to malloc...)
 	 * Note: this also handles cells == oldcells (a no-op).
 	 */
-	if (dp && cells <= oldcells && oldcells <= ICELLS) {
+	if (dp && cells <= oldcells) {
 		int split;
 
 		split = oldcells - cells;
@@ -411,7 +422,9 @@
 
 	/* If this is a large object, just free it up... */
 	/* Release object... */
-	if ((dp-1)->size > ICELLS) {
+	if ((dp-1)->size > ICELLS
+	    && (bp->last == dp + (dp-1)->size) /* don't free non-free blocks which have grown! */
+	   ) {
 		ablockfree(bp, ap);
 		ACHECK(ap);
 		return;
@@ -774,3 +787,127 @@
 # endif /* TEST_ALLOC */
 
 #endif /* MEM_DEBUG */
+
+#else /* DEBIAN */ /* patch from OpenBSD */
+
+/*	$OpenBSD: alloc.c,v 1.6 2003/08/05 20:52:27 millert Exp $	*/
+/*
+ * Copyright (c) 2002 Marc Espie.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
+ * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * area-based allocation built on malloc/free
+ */
+
+#include "sh.h"
+
+struct link {
+	struct link *prev;
+	struct link *next;
+};
+
+Area *
+ainit(Area *ap)
+{
+	ap->freelist = NULL;
+	return ap;
+}
+
+void
+afreeall(Area *ap)
+{
+	struct link *l, *l2;
+
+	for (l = ap->freelist; l != NULL; l = l2) {
+		l2 = l->next;
+		free(l);
+	}
+	ap->freelist = NULL;
+}
+
+#define L2P(l)	( (void *)(((char *)(l)) + sizeof(struct link)) )
+#define P2L(p)	( (struct link *)(((char *)(p)) - sizeof(struct link)) )
+
+void *
+alloc(size_t size, Area *ap)
+{
+	struct link *l;
+
+	l = malloc(size + sizeof(struct link));
+	if (l == NULL)
+		internal_errorf(1, "unable to allocate memory");
+	l->next = ap->freelist;
+	l->prev = NULL;
+	if (ap->freelist)
+		ap->freelist->prev = l;
+	ap->freelist = l;
+
+	return L2P(l);
+}
+
+void *
+aresize(void *ptr, size_t size, Area *ap)
+{
+	struct link *l, *l2, *lprev, *lnext;
+
+	if (ptr == NULL)
+		return alloc(size, ap);
+
+	l = P2L(ptr);
+	lprev = l->prev;
+	lnext = l->next;
+
+	l2 = realloc(l, size+sizeof(struct link));
+	if (l2 == NULL)
+		internal_errorf(1, "unable to allocate memory");
+	if (lprev)
+	    lprev->next = l2;
+	else
+	    ap->freelist = l2;
+	if (lnext)
+	    lnext->prev = l2;
+
+	return L2P(l2);
+}
+
+void
+afree(void *ptr, Area *ap)
+{
+	struct link *l;
+
+	if (!ptr)
+		return;
+
+	l = P2L(ptr);
+
+	if (l->prev)
+		l->prev->next = l->next;
+	else
+		ap->freelist = l->next;
+	if (l->next)
+		l->next->prev = l->prev;
+
+	free(l);
+}
+#endif /* DEBIAN */