Commit MetaInfo

Revision7b00b56bfbf3446f786255c6fee3f39c715b1a35 (tree)
Time2020-07-04 19:11:41
Authorsimphone
Commitersimphone

Log Message

electric fence 2.1 win32

Change Summary

Incremental Difference

diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/CHANGES
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/CHANGES Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,28 @@
1+Win32 Add page-win32.c, modified other files to compile on Win32 systems.
2+
3+2.1 Remove work-arounds, most operating systems and C libraries have
4+ been fixed now.
5+
6+2.0.1
7+ Add work-arounds for kernel and library bugs under HP-UX.
8+ HP has been notified and will repair these soon.
9+
10+2.0.2
11+ Add support for DEC Alpha. Add %a pattern for printing addresses, which
12+ assumes they are passed in a void *.
13+
14+2.0.3 30-Sep-1993
15+ When realloc is passed a zero address, it should work the same
16+ way as malloc(). Fix forward declaration of mprotect() in page.c to
17+ use void *, not caddr_t, for addresses. IRIX 5.0.1 complained about that.
18+
19+2.0.4 29-May-1994
20+ Don't attempt to allow access to a zero-sized page when
21+ EF_ALLOW_MALLOC_0 is set. Attempt to un-map memory from
22+ Page_Delete(). If that doesn't work, fall back by protecting the
23+ page from all references. Un-mapping small segments of a mapping
24+ used to crash my SGI IRIX 5.0 system. I assume that nobody is running
25+ 5.0 any longer.
26+
27+2.0.5 20-January-1995
28+ Port to Linux.
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/COPYING
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/COPYING Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,339 @@
1+ GNU GENERAL PUBLIC LICENSE
2+ Version 2, June 1991
3+
4+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5+ 675 Mass Ave, Cambridge, MA 02139, USA
6+ Everyone is permitted to copy and distribute verbatim copies
7+ of this license document, but changing it is not allowed.
8+
9+ Preamble
10+
11+ The licenses for most software are designed to take away your
12+freedom to share and change it. By contrast, the GNU General Public
13+License is intended to guarantee your freedom to share and change free
14+software--to make sure the software is free for all its users. This
15+General Public License applies to most of the Free Software
16+Foundation's software and to any other program whose authors commit to
17+using it. (Some other Free Software Foundation software is covered by
18+the GNU Library General Public License instead.) You can apply it to
19+your programs, too.
20+
21+ When we speak of free software, we are referring to freedom, not
22+price. Our General Public Licenses are designed to make sure that you
23+have the freedom to distribute copies of free software (and charge for
24+this service if you wish), that you receive source code or can get it
25+if you want it, that you can change the software or use pieces of it
26+in new free programs; and that you know you can do these things.
27+
28+ To protect your rights, we need to make restrictions that forbid
29+anyone to deny you these rights or to ask you to surrender the rights.
30+These restrictions translate to certain responsibilities for you if you
31+distribute copies of the software, or if you modify it.
32+
33+ For example, if you distribute copies of such a program, whether
34+gratis or for a fee, you must give the recipients all the rights that
35+you have. You must make sure that they, too, receive or can get the
36+source code. And you must show them these terms so they know their
37+rights.
38+
39+ We protect your rights with two steps: (1) copyright the software, and
40+(2) offer you this license which gives you legal permission to copy,
41+distribute and/or modify the software.
42+
43+ Also, for each author's protection and ours, we want to make certain
44+that everyone understands that there is no warranty for this free
45+software. If the software is modified by someone else and passed on, we
46+want its recipients to know that what they have is not the original, so
47+that any problems introduced by others will not reflect on the original
48+authors' reputations.
49+
50+ Finally, any free program is threatened constantly by software
51+patents. We wish to avoid the danger that redistributors of a free
52+program will individually obtain patent licenses, in effect making the
53+program proprietary. To prevent this, we have made it clear that any
54+patent must be licensed for everyone's free use or not licensed at all.
55+
56+ The precise terms and conditions for copying, distribution and
57+modification follow.
58+
59+ GNU GENERAL PUBLIC LICENSE
60+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61+
62+ 0. This License applies to any program or other work which contains
63+a notice placed by the copyright holder saying it may be distributed
64+under the terms of this General Public License. The "Program", below,
65+refers to any such program or work, and a "work based on the Program"
66+means either the Program or any derivative work under copyright law:
67+that is to say, a work containing the Program or a portion of it,
68+either verbatim or with modifications and/or translated into another
69+language. (Hereinafter, translation is included without limitation in
70+the term "modification".) Each licensee is addressed as "you".
71+
72+Activities other than copying, distribution and modification are not
73+covered by this License; they are outside its scope. The act of
74+running the Program is not restricted, and the output from the Program
75+is covered only if its contents constitute a work based on the
76+Program (independent of having been made by running the Program).
77+Whether that is true depends on what the Program does.
78+
79+ 1. You may copy and distribute verbatim copies of the Program's
80+source code as you receive it, in any medium, provided that you
81+conspicuously and appropriately publish on each copy an appropriate
82+copyright notice and disclaimer of warranty; keep intact all the
83+notices that refer to this License and to the absence of any warranty;
84+and give any other recipients of the Program a copy of this License
85+along with the Program.
86+
87+You may charge a fee for the physical act of transferring a copy, and
88+you may at your option offer warranty protection in exchange for a fee.
89+
90+ 2. You may modify your copy or copies of the Program or any portion
91+of it, thus forming a work based on the Program, and copy and
92+distribute such modifications or work under the terms of Section 1
93+above, provided that you also meet all of these conditions:
94+
95+ a) You must cause the modified files to carry prominent notices
96+ stating that you changed the files and the date of any change.
97+
98+ b) You must cause any work that you distribute or publish, that in
99+ whole or in part contains or is derived from the Program or any
100+ part thereof, to be licensed as a whole at no charge to all third
101+ parties under the terms of this License.
102+
103+ c) If the modified program normally reads commands interactively
104+ when run, you must cause it, when started running for such
105+ interactive use in the most ordinary way, to print or display an
106+ announcement including an appropriate copyright notice and a
107+ notice that there is no warranty (or else, saying that you provide
108+ a warranty) and that users may redistribute the program under
109+ these conditions, and telling the user how to view a copy of this
110+ License. (Exception: if the Program itself is interactive but
111+ does not normally print such an announcement, your work based on
112+ the Program is not required to print an announcement.)
113+
114+These requirements apply to the modified work as a whole. If
115+identifiable sections of that work are not derived from the Program,
116+and can be reasonably considered independent and separate works in
117+themselves, then this License, and its terms, do not apply to those
118+sections when you distribute them as separate works. But when you
119+distribute the same sections as part of a whole which is a work based
120+on the Program, the distribution of the whole must be on the terms of
121+this License, whose permissions for other licensees extend to the
122+entire whole, and thus to each and every part regardless of who wrote it.
123+
124+Thus, it is not the intent of this section to claim rights or contest
125+your rights to work written entirely by you; rather, the intent is to
126+exercise the right to control the distribution of derivative or
127+collective works based on the Program.
128+
129+In addition, mere aggregation of another work not based on the Program
130+with the Program (or with a work based on the Program) on a volume of
131+a storage or distribution medium does not bring the other work under
132+the scope of this License.
133+
134+ 3. You may copy and distribute the Program (or a work based on it,
135+under Section 2) in object code or executable form under the terms of
136+Sections 1 and 2 above provided that you also do one of the following:
137+
138+ a) Accompany it with the complete corresponding machine-readable
139+ source code, which must be distributed under the terms of Sections
140+ 1 and 2 above on a medium customarily used for software interchange; or,
141+
142+ b) Accompany it with a written offer, valid for at least three
143+ years, to give any third party, for a charge no more than your
144+ cost of physically performing source distribution, a complete
145+ machine-readable copy of the corresponding source code, to be
146+ distributed under the terms of Sections 1 and 2 above on a medium
147+ customarily used for software interchange; or,
148+
149+ c) Accompany it with the information you received as to the offer
150+ to distribute corresponding source code. (This alternative is
151+ allowed only for noncommercial distribution and only if you
152+ received the program in object code or executable form with such
153+ an offer, in accord with Subsection b above.)
154+
155+The source code for a work means the preferred form of the work for
156+making modifications to it. For an executable work, complete source
157+code means all the source code for all modules it contains, plus any
158+associated interface definition files, plus the scripts used to
159+control compilation and installation of the executable. However, as a
160+special exception, the source code distributed need not include
161+anything that is normally distributed (in either source or binary
162+form) with the major components (compiler, kernel, and so on) of the
163+operating system on which the executable runs, unless that component
164+itself accompanies the executable.
165+
166+If distribution of executable or object code is made by offering
167+access to copy from a designated place, then offering equivalent
168+access to copy the source code from the same place counts as
169+distribution of the source code, even though third parties are not
170+compelled to copy the source along with the object code.
171+
172+ 4. You may not copy, modify, sublicense, or distribute the Program
173+except as expressly provided under this License. Any attempt
174+otherwise to copy, modify, sublicense or distribute the Program is
175+void, and will automatically terminate your rights under this License.
176+However, parties who have received copies, or rights, from you under
177+this License will not have their licenses terminated so long as such
178+parties remain in full compliance.
179+
180+ 5. You are not required to accept this License, since you have not
181+signed it. However, nothing else grants you permission to modify or
182+distribute the Program or its derivative works. These actions are
183+prohibited by law if you do not accept this License. Therefore, by
184+modifying or distributing the Program (or any work based on the
185+Program), you indicate your acceptance of this License to do so, and
186+all its terms and conditions for copying, distributing or modifying
187+the Program or works based on it.
188+
189+ 6. Each time you redistribute the Program (or any work based on the
190+Program), the recipient automatically receives a license from the
191+original licensor to copy, distribute or modify the Program subject to
192+these terms and conditions. You may not impose any further
193+restrictions on the recipients' exercise of the rights granted herein.
194+You are not responsible for enforcing compliance by third parties to
195+this License.
196+
197+ 7. If, as a consequence of a court judgment or allegation of patent
198+infringement or for any other reason (not limited to patent issues),
199+conditions are imposed on you (whether by court order, agreement or
200+otherwise) that contradict the conditions of this License, they do not
201+excuse you from the conditions of this License. If you cannot
202+distribute so as to satisfy simultaneously your obligations under this
203+License and any other pertinent obligations, then as a consequence you
204+may not distribute the Program at all. For example, if a patent
205+license would not permit royalty-free redistribution of the Program by
206+all those who receive copies directly or indirectly through you, then
207+the only way you could satisfy both it and this License would be to
208+refrain entirely from distribution of the Program.
209+
210+If any portion of this section is held invalid or unenforceable under
211+any particular circumstance, the balance of the section is intended to
212+apply and the section as a whole is intended to apply in other
213+circumstances.
214+
215+It is not the purpose of this section to induce you to infringe any
216+patents or other property right claims or to contest validity of any
217+such claims; this section has the sole purpose of protecting the
218+integrity of the free software distribution system, which is
219+implemented by public license practices. Many people have made
220+generous contributions to the wide range of software distributed
221+through that system in reliance on consistent application of that
222+system; it is up to the author/donor to decide if he or she is willing
223+to distribute software through any other system and a licensee cannot
224+impose that choice.
225+
226+This section is intended to make thoroughly clear what is believed to
227+be a consequence of the rest of this License.
228+
229+ 8. If the distribution and/or use of the Program is restricted in
230+certain countries either by patents or by copyrighted interfaces, the
231+original copyright holder who places the Program under this License
232+may add an explicit geographical distribution limitation excluding
233+those countries, so that distribution is permitted only in or among
234+countries not thus excluded. In such case, this License incorporates
235+the limitation as if written in the body of this License.
236+
237+ 9. The Free Software Foundation may publish revised and/or new versions
238+of the General Public License from time to time. Such new versions will
239+be similar in spirit to the present version, but may differ in detail to
240+address new problems or concerns.
241+
242+Each version is given a distinguishing version number. If the Program
243+specifies a version number of this License which applies to it and "any
244+later version", you have the option of following the terms and conditions
245+either of that version or of any later version published by the Free
246+Software Foundation. If the Program does not specify a version number of
247+this License, you may choose any version ever published by the Free Software
248+Foundation.
249+
250+ 10. If you wish to incorporate parts of the Program into other free
251+programs whose distribution conditions are different, write to the author
252+to ask for permission. For software which is copyrighted by the Free
253+Software Foundation, write to the Free Software Foundation; we sometimes
254+make exceptions for this. Our decision will be guided by the two goals
255+of preserving the free status of all derivatives of our free software and
256+of promoting the sharing and reuse of software generally.
257+
258+ NO WARRANTY
259+
260+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268+REPAIR OR CORRECTION.
269+
270+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278+POSSIBILITY OF SUCH DAMAGES.
279+
280+ END OF TERMS AND CONDITIONS
281+
282+ How to Apply These Terms to Your New Programs
283+
284+ If you develop a new program, and you want it to be of the greatest
285+possible use to the public, the best way to achieve this is to make it
286+free software which everyone can redistribute and change under these terms.
287+
288+ To do so, attach the following notices to the program. It is safest
289+to attach them to the start of each source file to most effectively
290+convey the exclusion of warranty; and each file should have at least
291+the "copyright" line and a pointer to where the full notice is found.
292+
293+ <one line to give the program's name and a brief idea of what it does.>
294+ Copyright (C) 19yy <name of author>
295+
296+ This program is free software; you can redistribute it and/or modify
297+ it under the terms of the GNU General Public License as published by
298+ the Free Software Foundation; either version 2 of the License, or
299+ (at your option) any later version.
300+
301+ This program is distributed in the hope that it will be useful,
302+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304+ GNU General Public License for more details.
305+
306+ You should have received a copy of the GNU General Public License
307+ along with this program; if not, write to the Free Software
308+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
309+
310+Also add information on how to contact you by electronic and paper mail.
311+
312+If the program is interactive, make it output a short notice like this
313+when it starts in an interactive mode:
314+
315+ Gnomovision version 69, Copyright (C) 19yy name of author
316+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317+ This is free software, and you are welcome to redistribute it
318+ under certain conditions; type `show c' for details.
319+
320+The hypothetical commands `show w' and `show c' should show the appropriate
321+parts of the General Public License. Of course, the commands you use may
322+be called something other than `show w' and `show c'; they could even be
323+mouse-clicks or menu items--whatever suits your program.
324+
325+You should also get your employer (if you work as a programmer) or your
326+school, if any, to sign a "copyright disclaimer" for the program, if
327+necessary. Here is a sample; alter the names:
328+
329+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331+
332+ <signature of Ty Coon>, 1 April 1989
333+ Ty Coon, President of Vice
334+
335+This General Public License does not permit incorporating your program into
336+proprietary programs. If your program is a subroutine library, you may
337+consider it more useful to permit linking proprietary applications with the
338+library. If this is what you want to do, use the GNU Library General
339+Public License instead of this License.
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/Makefile Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,72 @@
1+ASFLAGS= -mips2
2+CC= cc
3+AR= ar
4+INSTALL= install
5+MV= mv
6+CHMOD= chmod
7+CFLAGS= -g
8+LIB_INSTALL_DIR= /usr/lib
9+MAN_INSTALL_DIR= /usr/man/man3
10+
11+PACKAGE_SOURCE= README libefence.3 Makefile efence.h \
12+ efence.c page.c print.c eftest.c tstheap.c CHANGES COPYING
13+
14+# Un-comment the following if you are running HP/UX.
15+# CFLAGS= -Aa -g -D_HPUX_SOURCE -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
16+
17+# Un-comment the following if you are running AIX. This makes sure you won't
18+# get the shared-library malloc() rather than the Electric Fence malloc().
19+# COMPILE THE PROGRAMS YOU ARE DEBUGGING WITH THESE FLAGS, TOO.
20+# CFLAGS= -g -bnso -bnodelcsect -bI:/lib/syscalls.exp
21+
22+# Un-comment the following if you are running SunOS 4.X
23+# Note the definition of PAGE_PROTECTION_VIOLATED_SIGNAL. This may vary
24+# depend on what version of Sun hardware you have.
25+# You'll probably have to link the program you are debugging with -Bstatic
26+# as well if using Sun's compiler, -static if using GCC.
27+# CFLAGS= -g -Bstatic -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
28+
29+OBJECTS= efence.o page.o print.o
30+
31+all: libefence.a tstheap eftest
32+ @ echo
33+ @ echo "Testing Electric Fence."
34+ @ echo "After the last test, it should print that the test has PASSED."
35+ ./eftest
36+ ./tstheap 3072
37+ @ echo
38+ @ echo "Electric Fence confidence test PASSED."
39+ @ echo
40+
41+install: libefence.a libefence.3
42+ $(MV) libefence.a $(LIB_INSTALL_DIR)
43+ $(CHMOD) 644 $(LIB_INSTALL_DIR)/libefence.a
44+ $(INSTALL) libefence.3 $(MAN_INSTALL_DIR)/libefence.3
45+ $(CHMOD) 644 $(MAN_INSTALL_DIR)/libefence.3
46+
47+clean:
48+ - rm -f $(OBJECTS) tstheap.o eftest.o tstheap eftest libefence.a \
49+ libefence.cat ElectricFence.shar
50+
51+roff:
52+ nroff -man < libefence.3 > libefence.cat
53+
54+
55+ElectricFence.shar: $(PACKAGE_SOURCE)
56+ shar $(PACKAGE_SOURCE) > ElectricFence.shar
57+
58+shar: ElectricFence.shar
59+
60+libefence.a: $(OBJECTS)
61+ - rm -f libefence.a
62+ $(AR) crv libefence.a $(OBJECTS)
63+
64+tstheap: libefence.a tstheap.o
65+ - rm -f tstheap
66+ $(CC) $(CFLAGS) tstheap.o libefence.a -o tstheap -lpthread
67+
68+eftest: libefence.a eftest.o
69+ - rm -f eftest
70+ $(CC) $(CFLAGS) eftest.o libefence.a -o eftest -lpthread
71+
72+$(OBJECTS) tstheap.o eftest.o: efence.h
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/README Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,46 @@
1+This is Electric Fence 2.1
2+
3+Electric Fence is a different kind of malloc() debugger. It uses the virtual
4+memory hardware of your system to detect when software overruns the boundaries
5+of a malloc() buffer. It will also detect any accesses of memory that has
6+been released by free(). Because it uses the VM hardware for detection,
7+Electric Fence stops your program on the first instruction that causes
8+a bounds violation. It's then trivial to use a debugger to display the
9+offending statement.
10+
11+This version will run on:
12+ Linux kernel version 1.1.83 and above. Earlier kernels have problems
13+ with the memory protection implementation.
14+
15+ All System V Revision 4 platforms (and possibly earlier revisions)
16+ including:
17+ Every 386 System V I've heard of.
18+ Solaris 2.x
19+ SGI IRIX 5.0 (but not 4.x)
20+
21+ IBM AIX on the RS/6000.
22+
23+ SunOS 4.X (using an ANSI C compiler and probably static linking).
24+
25+ HP/UX 9.01, and possibly earlier versions.
26+
27+ OSF 1.3 (and possibly earlier versions) on a DECalpha.
28+
29+On some of these platforms, you'll have to uncomment lines in the Makefile
30+that apply to your particular system.
31+
32+If you test Electric Fence on a platform not mentioned here, please send me a
33+report.
34+
35+It will probably port to any ANSI/POSIX system that provides mmap(), and
36+mprotect(), as long as mprotect() has the capability to turn off all access
37+to a memory page, and mmap() can use /dev/zero or the MAP_ANONYMOUS flag
38+to create virtual memory pages.
39+
40+Complete information on the use of Electric Fence is in the manual page
41+libefence.3 .
42+
43+ Thanks
44+
45+ Bruce Perens
46+ Bruce@Pixar.com
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/README.win32
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/README.win32 Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,8 @@
1+You've probably noticed by now that I haven't included any Win32 project
2+or make files.
3+
4+Since you need to modify your own project anyway, simply add efence.c,
5+page-win32.c, and print.c to your project.
6+
7+Peter Harris
8+peter.harris@hummingbird.com
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/efence.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/efence.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,907 @@
1+/*
2+ * Electric Fence - Red-Zone memory allocator.
3+ * Bruce Perens, 1988, 1993
4+ *
5+ * This is a special version of malloc() and company for debugging software
6+ * that is suspected of overrunning or underrunning the boundaries of a
7+ * malloc buffer, or touching free memory.
8+ *
9+ * It arranges for each malloc buffer to be followed (or preceded)
10+ * in the address space by an inaccessable virtual memory page,
11+ * and for free memory to be inaccessable. If software touches the
12+ * inaccessable page, it will get an immediate segmentation
13+ * fault. It is then trivial to uncover the offending code using a debugger.
14+ *
15+ * An advantage of this product over most malloc debuggers is that this one
16+ * detects reading out of bounds as well as writing, and this one stops on
17+ * the exact instruction that causes the error, rather than waiting until the
18+ * next boundary check.
19+ *
20+ * There is one product that debugs malloc buffer overruns
21+ * better than Electric Fence: "Purify" from Purify Systems, and that's only
22+ * a small part of what Purify does. I'm not affiliated with Purify, I just
23+ * respect a job well done.
24+ *
25+ * This version of malloc() should not be linked into production software,
26+ * since it tremendously increases the time and memory overhead of malloc().
27+ * Each malloc buffer will consume a minimum of two virtual memory pages,
28+ * this is 16 kilobytes on many systems. On some systems it will be necessary
29+ * to increase the amount of swap space in order to debug large programs that
30+ * perform lots of allocation, because of the per-buffer overhead.
31+ *
32+ * Win32 tweaks
33+ * Peter Harris, 2007
34+ */
35+#include "efence.h"
36+#include <stdlib.h>
37+#ifndef _WIN32
38+#include <unistd.h>
39+#endif
40+#include <memory.h>
41+#include <string.h>
42+#ifndef _WIN32
43+#include <pthread.h>
44+#endif
45+
46+#ifdef malloc
47+#undef malloc
48+#endif
49+
50+#ifdef calloc
51+#undef calloc
52+#endif
53+
54+#ifdef realloc
55+#undef realloc
56+#endif
57+
58+#ifdef free
59+#undef free
60+#endif
61+
62+#define malloc EF_malloc
63+#define calloc EF_calloc
64+#define realloc EF_realloc
65+#define free EF_free
66+
67+static const char version[] = "\n Electric Fence 2.1"
68+ " Copyright (C) 1987-1998 Bruce Perens.\n";
69+
70+/*
71+ * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
72+ * system at one time. We'll break that memory down into smaller pieces for
73+ * malloc buffers. One megabyte is probably a good value.
74+ */
75+#define MEMORY_CREATION_SIZE 1024 * 1024
76+
77+/*
78+ * Enum Mode indicates the status of a malloc buffer.
79+ */
80+enum _Mode {
81+ NOT_IN_USE = 0, /* Available to represent a malloc buffer. */
82+ FREE, /* A free buffer. */
83+ ALLOCATED, /* A buffer that is in use. */
84+ PROTECTED, /* A freed buffer that can not be allocated again. */
85+ INTERNAL_USE /* A buffer used internally by malloc(). */
86+};
87+typedef enum _Mode Mode;
88+
89+/*
90+ * Struct Slot contains all of the information about a malloc buffer except
91+ * for the contents of its memory.
92+ */
93+struct _Slot {
94+ void * userAddress;
95+ void * internalAddress;
96+ size_t userSize;
97+ size_t internalSize;
98+ Mode mode;
99+};
100+typedef struct _Slot Slot;
101+
102+ /*
103+ * EF_DISABLE_BANNER is a global variable used to control whether
104+ * Electric Fence prints its usual startup message. If the value is
105+ * -1, it will be set from the environment default to 0 at run time.
106+ */
107+int EF_DISABLE_BANNER = -1;
108+
109+
110+/*
111+ * EF_ALIGNMENT is a global variable used to control the default alignment
112+ * of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
113+ * so that its name matches the name of the environment variable that is used
114+ * to set it. This gives the programmer one less name to remember.
115+ * If the value is -1, it will be set from the environment or sizeof(int)
116+ * at run time.
117+ */
118+int EF_ALIGNMENT = -1;
119+
120+/*
121+ * EF_PROTECT_FREE is a global variable used to control the disposition of
122+ * memory that is released using free(). It is all-caps so that its name
123+ * matches the name of the environment variable that is used to set it.
124+ * If its value is greater non-zero, memory released by free is made
125+ * inaccessable and never allocated again. Any software that touches free
126+ * memory will then get a segmentation fault. If its value is zero, freed
127+ * memory will be available for reallocation, but will still be inaccessable
128+ * until it is reallocated.
129+ * If the value is -1, it will be set from the environment or to 0 at run-time.
130+ */
131+int EF_PROTECT_FREE = -1;
132+
133+/*
134+ * EF_PROTECT_BELOW is used to modify the behavior of the allocator. When
135+ * its value is non-zero, the allocator will place an inaccessable page
136+ * immediately _before_ the malloc buffer in the address space, instead
137+ * of _after_ it. Use this to detect malloc buffer under-runs, rather than
138+ * over-runs. It won't detect both at the same time, so you should test your
139+ * software twice, once with this value clear, and once with it set.
140+ * If the value is -1, it will be set from the environment or to zero at
141+ * run-time
142+ */
143+int EF_PROTECT_BELOW = -1;
144+
145+/*
146+ * EF_ALLOW_MALLOC_0 is set if Electric Fence is to allow malloc(0). I
147+ * trap malloc(0) by default because it is a common source of bugs.
148+ */
149+int EF_ALLOW_MALLOC_0 = -1;
150+
151+/*
152+ * EF_FREE_WIPES is set if Electric Fence is to wipe the memory content
153+ * of freed blocks. This makes it easier to check if memory is freed or
154+ * not
155+ */
156+int EF_FREE_WIPES = -1;
157+
158+/*
159+ * allocationList points to the array of slot structures used to manage the
160+ * malloc arena.
161+ */
162+static Slot * allocationList = 0;
163+
164+/*
165+ * allocationListSize is the size of the allocation list. This will always
166+ * be a multiple of the page size.
167+ */
168+static size_t allocationListSize = 0;
169+
170+/*
171+ * slotCount is the number of Slot structures in allocationList.
172+ */
173+static size_t slotCount = 0;
174+
175+/*
176+ * unUsedSlots is the number of Slot structures that are currently available
177+ * to represent new malloc buffers. When this number gets too low, we will
178+ * create new slots.
179+ */
180+static size_t unUsedSlots = 0;
181+
182+/*
183+ * slotsPerPage is the number of slot structures that fit in a virtual
184+ * memory page.
185+ */
186+static size_t slotsPerPage = 0;
187+
188+/*
189+ * internalUse is set when allocating and freeing the allocatior-internal
190+ * data structures.
191+ */
192+static int internalUse = 0;
193+
194+/*
195+ * noAllocationListProtection is set to tell malloc() and free() not to
196+ * manipulate the protection of the allocation list. This is only set in
197+ * realloc(), which does it to save on slow system calls, and in
198+ * allocateMoreSlots(), which does it because it changes the allocation list.
199+ */
200+static int noAllocationListProtection = 0;
201+
202+/*
203+ * bytesPerPage is set at run-time to the number of bytes per virtual-memory
204+ * page, as returned by Page_Size().
205+ */
206+static size_t bytesPerPage = 0;
207+
208+ /*
209+ * mutex to enable multithreaded operation
210+ */
211+#ifdef _WIN32
212+CRITICAL_SECTION mutex;
213+#else
214+static pthread_mutex_t mutex ;
215+static pid_t mutexpid=0;
216+static int locknr=0;
217+#endif
218+
219+
220+static void lock() {
221+#ifdef _WIN32
222+ EnterCriticalSection(&mutex);
223+#else
224+ if (pthread_mutex_trylock(&mutex)) {
225+ if (mutexpid==getpid()) {
226+ locknr++;
227+ return;
228+ } else {
229+ pthread_mutex_lock(&mutex);
230+ }
231+ }
232+ mutexpid=getpid();
233+ locknr=1;
234+#endif
235+}
236+
237+static void unlock() {
238+#ifdef _WIN32
239+ LeaveCriticalSection(&mutex);
240+#else
241+ locknr--;
242+ if (!locknr) {
243+ mutexpid=0;
244+ pthread_mutex_unlock(&mutex);
245+ }
246+#endif
247+}
248+
249+/*
250+ * internalError is called for those "shouldn't happen" errors in the
251+ * allocator.
252+ */
253+static void
254+internalError(void)
255+{
256+ EF_Abort("Internal error in allocator.");
257+}
258+
259+/*
260+ * initialize sets up the memory allocation arena and the run-time
261+ * configuration information.
262+ */
263+static void
264+initialize(void)
265+{
266+ size_t size = MEMORY_CREATION_SIZE;
267+ size_t slack;
268+ char * string;
269+ Slot * slot;
270+
271+ if ( EF_DISABLE_BANNER == -1 ) {
272+ if ( (string = getenv("EF_DISABLE_BANNER")) != 0 )
273+ EF_DISABLE_BANNER = atoi(string);
274+ else
275+ EF_DISABLE_BANNER = 0;
276+ }
277+
278+ if ( EF_DISABLE_BANNER == 0 )
279+ EF_Print(version);
280+
281+ /*
282+ * Import the user's environment specification of the default
283+ * alignment for malloc(). We want that alignment to be under
284+ * user control, since smaller alignment lets us catch more bugs,
285+ * however some software will break if malloc() returns a buffer
286+ * that is not word-aligned.
287+ *
288+ * I would like
289+ * alignment to be zero so that we could catch all one-byte
290+ * overruns, however if malloc() is asked to allocate an odd-size
291+ * buffer and returns an address that is not word-aligned, or whose
292+ * size is not a multiple of the word size, software breaks.
293+ * This was the case with the Sun string-handling routines,
294+ * which can do word fetches up to three bytes beyond the end of a
295+ * string. I handle this problem in part by providing
296+ * byte-reference-only versions of the string library functions, but
297+ * there are other functions that break, too. Some in X Windows, one
298+ * in Sam Leffler's TIFF library, and doubtless many others.
299+ */
300+ if ( EF_ALIGNMENT == -1 ) {
301+ if ( (string = getenv("EF_ALIGNMENT")) != 0 )
302+ EF_ALIGNMENT = (size_t)atoi(string);
303+ else
304+ EF_ALIGNMENT = sizeof(int);
305+ }
306+
307+ /*
308+ * See if the user wants to protect the address space below a buffer,
309+ * rather than that above a buffer.
310+ */
311+ if ( EF_PROTECT_BELOW == -1 ) {
312+ if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
313+ EF_PROTECT_BELOW = (atoi(string) != 0);
314+ else
315+ EF_PROTECT_BELOW = 0;
316+ }
317+
318+ /*
319+ * See if the user wants to protect memory that has been freed until
320+ * the program exits, rather than until it is re-allocated.
321+ */
322+ if ( EF_PROTECT_FREE == -1 ) {
323+ if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
324+ EF_PROTECT_FREE = (atoi(string) != 0);
325+ else
326+#ifdef _WIN64
327+ /* On windows, we decommit memory if we know we'll never
328+ use it again. On win64, we should have enough address
329+ space available that we never need to free, so turn
330+ this flag on by default. */
331+ EF_PROTECT_FREE = 1;
332+#else
333+ EF_PROTECT_FREE = 0;
334+#endif
335+ }
336+
337+ /*
338+ * See if the user wants to allow malloc(0).
339+ */
340+ if ( EF_ALLOW_MALLOC_0 == -1 ) {
341+ if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
342+ EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
343+ else
344+ EF_ALLOW_MALLOC_0 = 0;
345+ }
346+
347+ /*
348+ * See if the user wants us to wipe out freed memory.
349+ */
350+ if ( EF_FREE_WIPES == -1 ) {
351+ if ( (string = getenv("EF_FREE_WIPES")) != 0 )
352+ EF_FREE_WIPES = (atoi(string) != 0);
353+ else
354+ EF_FREE_WIPES = 0;
355+ }
356+
357+ /*
358+ * Get the run-time configuration of the virtual memory page size.
359+ */
360+ bytesPerPage = Page_Size();
361+
362+ /*
363+ * Figure out how many Slot structures to allocate at one time.
364+ */
365+ slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
366+ allocationListSize = bytesPerPage;
367+
368+ if ( allocationListSize > size )
369+ size = allocationListSize;
370+
371+ if ( (slack = size % bytesPerPage) != 0 )
372+ size += bytesPerPage - slack;
373+
374+ /*
375+ * Allocate memory, and break it up into two malloc buffers. The
376+ * first buffer will be used for Slot structures, the second will
377+ * be marked free.
378+ */
379+ slot = allocationList = (Slot *)Page_Create(size);
380+ memset((char *)allocationList, 0, allocationListSize);
381+
382+ slot[0].internalSize = slot[0].userSize = allocationListSize;
383+ slot[0].internalAddress = slot[0].userAddress = allocationList;
384+ slot[0].mode = INTERNAL_USE;
385+ if ( size > allocationListSize ) {
386+ slot[1].internalAddress = slot[1].userAddress
387+ = ((char *)slot[0].internalAddress) + slot[0].internalSize;
388+ slot[1].internalSize
389+ = slot[1].userSize = size - slot[0].internalSize;
390+ slot[1].mode = FREE;
391+ }
392+
393+ /*
394+ * Deny access to the free page, so that we will detect any software
395+ * that treads upon free memory.
396+ */
397+ Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);
398+
399+ /*
400+ * Account for the two slot structures that we've used.
401+ */
402+ unUsedSlots = slotCount - 2;
403+}
404+
405+/*
406+ * allocateMoreSlots is called when there are only enough slot structures
407+ * left to support the allocation of a single malloc buffer.
408+ */
409+static void
410+allocateMoreSlots(void)
411+{
412+ size_t newSize = allocationListSize + bytesPerPage;
413+ void * newAllocation;
414+ void * oldAllocation = allocationList;
415+
416+ Page_AllowAccess(allocationList, allocationListSize);
417+ noAllocationListProtection = 1;
418+ internalUse = 1;
419+
420+ newAllocation = malloc(newSize);
421+ memcpy(newAllocation, allocationList, allocationListSize);
422+ memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
423+
424+ allocationList = (Slot *)newAllocation;
425+ allocationListSize = newSize;
426+ slotCount += slotsPerPage;
427+ unUsedSlots += slotsPerPage;
428+
429+ free(oldAllocation);
430+
431+ /*
432+ * Keep access to the allocation list open at this point, because
433+ * I am returning to memalign(), which needs that access.
434+ */
435+ noAllocationListProtection = 0;
436+ internalUse = 0;
437+}
438+
439+/*
440+ * This is the memory allocator. When asked to allocate a buffer, allocate
441+ * it in such a way that the end of the buffer is followed by an inaccessable
442+ * memory page. If software overruns that buffer, it will touch the bad page
443+ * and get an immediate segmentation fault. It's then easy to zero in on the
444+ * offending code with a debugger.
445+ *
446+ * There are a few complications. If the user asks for an odd-sized buffer,
447+ * we would have to have that buffer start on an odd address if the byte after
448+ * the end of the buffer was to be on the inaccessable page. Unfortunately,
449+ * there is lots of software that asks for odd-sized buffers and then
450+ * requires that the returned address be word-aligned, or the size of the
451+ * buffer be a multiple of the word size. An example are the string-processing
452+ * functions on Sun systems, which do word references to the string memory
453+ * and may refer to memory up to three bytes beyond the end of the string.
454+ * For this reason, I take the alignment requests to memalign() and valloc()
455+ * seriously, and
456+ *
457+ * Electric Fence wastes lots of memory. I do a best-fit allocator here
458+ * so that it won't waste even more. It's slow, but thrashing because your
459+ * working set is too big for a system's RAM is even slower.
460+ */
461+extern C_LINKAGE void *
462+memalign(size_t alignment, size_t userSize)
463+{
464+ register Slot * slot;
465+ register size_t count;
466+ Slot * fullSlot = 0;
467+ Slot * emptySlots[2];
468+ size_t internalSize;
469+ size_t slack;
470+ char * address;
471+
472+ if ( allocationList == 0 )
473+ initialize();
474+
475+ if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
476+ EF_Abort("Allocating 0 bytes, probably a bug.");
477+
478+ /*
479+ * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
480+ * and company will be page-aligned.
481+ */
482+ if ( !EF_PROTECT_BELOW && alignment > 1 ) {
483+ if ( (slack = userSize % alignment) != 0 )
484+ userSize += alignment - slack;
485+ }
486+
487+ /*
488+ * The internal size of the buffer is rounded up to the next page-size
489+ * boudary, and then we add another page's worth of memory for the
490+ * dead page.
491+ */
492+ internalSize = userSize + bytesPerPage;
493+ if ( (slack = internalSize % bytesPerPage) != 0 )
494+ internalSize += bytesPerPage - slack;
495+
496+ /*
497+ * These will hold the addresses of two empty Slot structures, that
498+ * can be used to hold information for any memory I create, and any
499+ * memory that I mark free.
500+ */
501+ emptySlots[0] = 0;
502+ emptySlots[1] = 0;
503+
504+ /*
505+ * The internal memory used by the allocator is currently
506+ * inaccessable, so that errant programs won't scrawl on the
507+ * allocator's arena. I'll un-protect it here so that I can make
508+ * a new allocation. I'll re-protect it before I return.
509+ */
510+ if ( !noAllocationListProtection )
511+ Page_AllowAccess(allocationList, allocationListSize);
512+
513+ /*
514+ * If I'm running out of empty slots, create some more before
515+ * I don't have enough slots left to make an allocation.
516+ */
517+ if ( !internalUse && unUsedSlots < 7 ) {
518+ allocateMoreSlots();
519+ }
520+
521+ /*
522+ * Iterate through all of the slot structures. Attempt to find a slot
523+ * containing free memory of the exact right size. Accept a slot with
524+ * more memory than we want, if the exact right size is not available.
525+ * Find two slot structures that are not in use. We will need one if
526+ * we split a buffer into free and allocated parts, and the second if
527+ * we have to create new memory and mark it as free.
528+ *
529+ */
530+
531+ for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
532+ if ( slot->mode == FREE
533+ && slot->internalSize >= internalSize ) {
534+ if ( !fullSlot
535+ ||slot->internalSize < fullSlot->internalSize){
536+ fullSlot = slot;
537+ if ( slot->internalSize == internalSize
538+ && emptySlots[0] )
539+ break; /* All done, */
540+ }
541+ }
542+ else if ( slot->mode == NOT_IN_USE ) {
543+ if ( !emptySlots[0] )
544+ emptySlots[0] = slot;
545+ else if ( !emptySlots[1] )
546+ emptySlots[1] = slot;
547+ else if ( fullSlot
548+ && fullSlot->internalSize == internalSize )
549+ break; /* All done. */
550+ }
551+ slot++;
552+ }
553+ if ( !emptySlots[0] )
554+ internalError();
555+
556+ if ( !fullSlot ) {
557+ /*
558+ * I get here if I haven't been able to find a free buffer
559+ * with all of the memory I need. I'll have to create more
560+ * memory. I'll mark it all as free, and then split it into
561+ * free and allocated portions later.
562+ */
563+ size_t chunkSize = MEMORY_CREATION_SIZE;
564+
565+ if ( !emptySlots[1] )
566+ internalError();
567+
568+ if ( chunkSize < internalSize )
569+ chunkSize = internalSize;
570+
571+ if ( (slack = chunkSize % bytesPerPage) != 0 )
572+ chunkSize += bytesPerPage - slack;
573+
574+ /* Use up one of the empty slots to make the full slot. */
575+ fullSlot = emptySlots[0];
576+ emptySlots[0] = emptySlots[1];
577+ fullSlot->internalAddress = Page_Create(chunkSize);
578+ fullSlot->internalSize = chunkSize;
579+ fullSlot->mode = FREE;
580+ unUsedSlots--;
581+ }
582+
583+ /*
584+ * If I'm allocating memory for the allocator's own data structures,
585+ * mark it INTERNAL_USE so that no errant software will be able to
586+ * free it.
587+ */
588+ if ( internalUse )
589+ fullSlot->mode = INTERNAL_USE;
590+ else
591+ fullSlot->mode = ALLOCATED;
592+
593+ /*
594+ * If the buffer I've found is larger than I need, split it into
595+ * an allocated buffer with the exact amount of memory I need, and
596+ * a free buffer containing the surplus memory.
597+ */
598+ if ( fullSlot->internalSize > internalSize ) {
599+ emptySlots[0]->internalSize
600+ = fullSlot->internalSize - internalSize;
601+ emptySlots[0]->internalAddress
602+ = ((char *)fullSlot->internalAddress) + internalSize;
603+ emptySlots[0]->mode = FREE;
604+ fullSlot->internalSize = internalSize;
605+ unUsedSlots--;
606+ }
607+
608+ if ( !EF_PROTECT_BELOW ) {
609+ /*
610+ * Arrange the buffer so that it is followed by an inaccessable
611+ * memory page. A buffer overrun that touches that page will
612+ * cause a segmentation fault.
613+ */
614+ address = (char *)fullSlot->internalAddress;
615+
616+ /* Set up the "live" page. */
617+ if ( internalSize - bytesPerPage > 0 )
618+ Page_AllowAccess(
619+ fullSlot->internalAddress
620+ ,internalSize - bytesPerPage);
621+
622+ address += internalSize - bytesPerPage;
623+
624+ /* Set up the "dead" page. */
625+ Page_DenyAccess(address, bytesPerPage);
626+
627+ /* Figure out what address to give the user. */
628+ address -= userSize;
629+ }
630+ else { /* EF_PROTECT_BELOW != 0 */
631+ /*
632+ * Arrange the buffer so that it is preceded by an inaccessable
633+ * memory page. A buffer underrun that touches that page will
634+ * cause a segmentation fault.
635+ */
636+ address = (char *)fullSlot->internalAddress;
637+
638+ /* Set up the "dead" page. */
639+ Page_DenyAccess(address, bytesPerPage);
640+
641+ address += bytesPerPage;
642+
643+ /* Set up the "live" page. */
644+ if ( internalSize - bytesPerPage > 0 )
645+ Page_AllowAccess(address, internalSize - bytesPerPage);
646+ }
647+
648+ fullSlot->userAddress = address;
649+ fullSlot->userSize = userSize;
650+
651+ /*
652+ * Make the pool's internal memory inaccessable, so that the program
653+ * being debugged can't stomp on it.
654+ */
655+ if ( !internalUse )
656+ Page_DenyAccess(allocationList, allocationListSize);
657+
658+ return address;
659+}
660+
661+/*
662+ * Find the slot structure for a user address.
663+ */
664+static Slot *
665+slotForUserAddress(void * address)
666+{
667+ register Slot * slot = allocationList;
668+ register size_t count = slotCount;
669+
670+ for ( ; count > 0; count-- ) {
671+ if ( slot->userAddress == address )
672+ return slot;
673+ slot++;
674+ }
675+
676+ return 0;
677+}
678+
679+/*
680+ * Find the slot structure for an internal address.
681+ */
682+static Slot *
683+slotForInternalAddress(void * address)
684+{
685+ register Slot * slot = allocationList;
686+ register size_t count = slotCount;
687+
688+ for ( ; count > 0; count-- ) {
689+ if ( slot->internalAddress == address )
690+ return slot;
691+ slot++;
692+ }
693+ return 0;
694+}
695+
696+/*
697+ * Given the internal address of a buffer, find the buffer immediately
698+ * before that buffer in the address space. This is used by free() to
699+ * coalesce two free buffers into one.
700+ */
701+static Slot *
702+slotForInternalAddressPreviousTo(void * address)
703+{
704+ register Slot * slot = allocationList;
705+ register size_t count = slotCount;
706+
707+ for ( ; count > 0; count-- ) {
708+ if ( ((char *)slot->internalAddress)
709+ + slot->internalSize == address )
710+ return slot;
711+ slot++;
712+ }
713+ return 0;
714+}
715+
716+extern C_LINKAGE void
717+free(void * address)
718+{
719+ Slot * slot;
720+ Slot * previousSlot = 0;
721+ Slot * nextSlot = 0;
722+
723+ lock();
724+
725+ if ( address == 0 ) {
726+ unlock();
727+ return;
728+ }
729+
730+ if ( allocationList == 0 )
731+ EF_Abort("free() called before first malloc().");
732+
733+ if ( !noAllocationListProtection )
734+ Page_AllowAccess(allocationList, allocationListSize);
735+
736+ slot = slotForUserAddress(address);
737+
738+ if ( !slot )
739+ EF_Abort("free(%a): address not from malloc().", address);
740+
741+ if ( slot->mode != ALLOCATED ) {
742+ if ( internalUse && slot->mode == INTERNAL_USE )
743+ /* Do nothing. */;
744+ else {
745+ EF_Abort(
746+ "free(%a): freeing free memory."
747+ ,address);
748+ }
749+ }
750+
751+ if ( EF_PROTECT_FREE )
752+ slot->mode = PROTECTED;
753+ else
754+ slot->mode = FREE;
755+
756+ if ( EF_FREE_WIPES )
757+ memset(slot->userAddress, 0xbd, slot->userSize);
758+
759+ previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
760+ nextSlot = slotForInternalAddress(
761+ ((char *)slot->internalAddress) + slot->internalSize);
762+
763+ if ( previousSlot
764+ && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
765+ /* Coalesce previous slot with this one. */
766+ previousSlot->internalSize += slot->internalSize;
767+ if ( EF_PROTECT_FREE )
768+ previousSlot->mode = PROTECTED;
769+
770+ slot->internalAddress = slot->userAddress = 0;
771+ slot->internalSize = slot->userSize = 0;
772+ slot->mode = NOT_IN_USE;
773+ slot = previousSlot;
774+ unUsedSlots++;
775+ }
776+ if ( nextSlot
777+ && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
778+ /* Coalesce next slot with this one. */
779+ slot->internalSize += nextSlot->internalSize;
780+ nextSlot->internalAddress = nextSlot->userAddress = 0;
781+ nextSlot->internalSize = nextSlot->userSize = 0;
782+ nextSlot->mode = NOT_IN_USE;
783+ unUsedSlots++;
784+ }
785+
786+ slot->userAddress = slot->internalAddress;
787+ slot->userSize = slot->internalSize;
788+
789+ /*
790+ * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
791+ * is true, free memory is never reallocated, so it remains access
792+ * denied for the life of the process. When EF_PROTECT_FREE is false,
793+ * the memory may be re-allocated, at which time access to it will be
794+ * allowed again.
795+ */
796+ if (slot->mode == PROTECTED)
797+ Page_Delete(slot->internalAddress, slot->internalSize);
798+ else
799+ Page_DenyAccess(slot->internalAddress, slot->internalSize);
800+
801+ if ( !noAllocationListProtection )
802+ Page_DenyAccess(allocationList, allocationListSize);
803+
804+ unlock();
805+}
806+
807+extern C_LINKAGE void *
808+realloc(void * oldBuffer, size_t newSize)
809+{
810+ void * newBuffer = malloc(newSize);
811+
812+ lock();
813+
814+ if ( oldBuffer ) {
815+ size_t size;
816+ Slot * slot;
817+
818+ Page_AllowAccess(allocationList, allocationListSize);
819+ noAllocationListProtection = 1;
820+
821+ slot = slotForUserAddress(oldBuffer);
822+
823+ if ( slot == 0 )
824+ EF_Abort(
825+ "realloc(%a, %d): address not from malloc()."
826+ ,oldBuffer
827+ ,newSize);
828+
829+ if ( newSize < (size = slot->userSize) )
830+ size = newSize;
831+
832+ if ( size > 0 )
833+ memcpy(newBuffer, oldBuffer, size);
834+
835+ free(oldBuffer);
836+ noAllocationListProtection = 0;
837+ Page_DenyAccess(allocationList, allocationListSize);
838+
839+ if ( size < newSize )
840+ memset(&(((char *)newBuffer)[size]), 0, newSize - size);
841+
842+ /* Internal memory was re-protected in free() */
843+ }
844+ unlock();
845+
846+ return newBuffer;
847+}
848+
849+extern C_LINKAGE void *
850+malloc(size_t size)
851+{
852+ void *allocation;
853+
854+ if ( allocationList == 0 ) {
855+#ifdef _WIN32
856+ InitializeCriticalSection(&mutex);
857+#else
858+ pthread_mutex_init(&mutex, NULL);
859+#endif
860+ initialize(); /* This sets EF_ALIGNMENT */
861+ }
862+ lock();
863+ allocation=memalign(EF_ALIGNMENT, size);
864+
865+ unlock();
866+
867+ return allocation;
868+}
869+
870+extern C_LINKAGE void *
871+calloc(size_t nelem, size_t elsize)
872+{
873+ size_t size = nelem * elsize;
874+ void * allocation;
875+
876+ if ( allocationList == 0 ) {
877+#ifdef _WIN32
878+ InitializeCriticalSection(&mutex);
879+#else
880+ pthread_mutex_init(&mutex, NULL);
881+#endif
882+ initialize(); /* This sets EF_ALIGNMENT */
883+ }
884+ lock();
885+
886+ allocation = malloc(size);
887+ memset(allocation, 0, size);
888+ unlock();
889+
890+ return allocation;
891+}
892+
893+/*
894+ * This will catch more bugs if you remove the page alignment, but it
895+ * will break some software.
896+ */
897+extern C_LINKAGE void *
898+valloc (size_t size)
899+{
900+ void * allocation;
901+
902+ lock();
903+ allocation= memalign(bytesPerPage, size);
904+ unlock();
905+
906+ return allocation;
907+}
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/efence.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/efence.h Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,77 @@
1+#ifdef _WIN32
2+#include <windows.h>
3+#else
4+#include <sys/types.h>
5+#include <sys/param.h>
6+#endif
7+
8+/*
9+ * ef_number is the largest unsigned integer we'll need. On systems that
10+ * support 64-bit pointers, this may be "unsigned long long".
11+ */
12+#ifdef _WIN32
13+typedef DWORD_PTR ef_number;
14+typedef DWORD_PTR caddr_t;
15+#else
16+#if defined(USE_LONG_LONG)
17+typedef unsigned long long ef_number;
18+#else
19+typedef unsigned long ef_number;
20+#endif
21+#endif
22+
23+/*
24+ * NBBY is the number of bits per byte. Some systems define it in
25+ * <sys/param.h> .
26+ */
27+#ifndef NBBY
28+#define NBBY 8
29+#endif
30+
31+/*
32+ * This is used to declare functions with "C" linkage if we are compiling
33+ * with C++ .
34+ */
35+#ifdef __cplusplus
36+#define C_LINKAGE "C"
37+#else
38+#define C_LINKAGE
39+#endif
40+
41+void Page_AllowAccess(void * address, size_t size);
42+void * Page_Create(size_t size);
43+void Page_Delete(void * address, size_t size);
44+void Page_DenyAccess(void * address, size_t size);
45+size_t Page_Size(void);
46+
47+void EF_Abort(const char * message, ...);
48+void EF_Exit(const char * message, ...);
49+void EF_Print(const char * message, ...);
50+void EF_Lock();
51+void EF_UnLock();
52+
53+#ifdef malloc
54+#undef malloc
55+#endif
56+
57+#ifdef calloc
58+#undef calloc
59+#endif
60+
61+#ifdef realloc
62+#undef realloc
63+#endif
64+
65+#ifdef free
66+#undef free
67+#endif
68+
69+#define malloc EF_malloc
70+#define calloc EF_calloc
71+#define realloc EF_realloc
72+#define free EF_free
73+
74+extern C_LINKAGE void free(void * address);
75+extern C_LINKAGE void *realloc(void * oldBuffer, size_t newSize);
76+extern C_LINKAGE void *malloc(size_t size);
77+extern C_LINKAGE void *calloc(size_t nelem, size_t elsize);
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/eftest.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/eftest.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,241 @@
1+#include <stdlib.h>
2+#include <stdio.h>
3+#include <string.h>
4+#ifndef _WIN32
5+#include <unistd.h>
6+#include <setjmp.h>
7+#include <signal.h>
8+#endif
9+#include "efence.h"
10+
11+/*
12+ * Electric Fence confidence tests.
13+ * Make sure all of the various functions of Electric Fence work correctly.
14+ */
15+
16+#ifndef PAGE_PROTECTION_VIOLATED_SIGNAL
17+#define PAGE_PROTECTION_VIOLATED_SIGNAL SIGSEGV
18+#endif
19+
20+struct diagnostic {
21+ int (*test)(void);
22+ int expectedStatus;
23+ const char * explanation;
24+};
25+
26+extern int EF_PROTECT_BELOW;
27+extern int EF_ALIGNMENT;
28+
29+#ifdef _WIN32
30+
31+static int
32+gotSegmentationFault(int (*test)(void))
33+{
34+ int rv;
35+ __try
36+ {
37+ rv = test();
38+ }
39+ __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
40+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
41+ {
42+ return 1;
43+ }
44+ return rv;
45+}
46+
47+#else
48+static sigjmp_buf env;
49+
50+/*
51+ * There is still too little standardization of the arguments and return
52+ * type of signal handler functions.
53+ */
54+static
55+void
56+segmentationFaultHandler(
57+int signalNumber
58+#if ( defined(_AIX) )
59+, ...
60+#endif
61+)
62+ {
63+ signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
64+ siglongjmp(env, 1);
65+}
66+
67+static int
68+gotSegmentationFault(int (*test)(void))
69+{
70+ if ( sigsetjmp(env,1) == 0 ) {
71+ int status;
72+
73+ signal(PAGE_PROTECTION_VIOLATED_SIGNAL
74+ ,segmentationFaultHandler);
75+ status = (*test)();
76+ signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
77+ return status;
78+ }
79+ else
80+ return 1;
81+}
82+#endif
83+
84+static char * allocation;
85+/* c is global so that assignments to it won't be optimized out. */
86+char c;
87+
88+static int
89+testSizes(void)
90+{
91+ /*
92+ * If ef_number can't hold all of the bits of a void *, have the user
93+ * add -DUSE_ LONG_LONG to the compiler flags so that ef_number will be
94+ * declared as "unsigned long long" instead of "unsigned long".
95+ */
96+ return ( sizeof(ef_number) < sizeof(void *) );
97+}
98+
99+static int
100+allocateMemory(void)
101+{
102+ allocation = (char *)malloc(1);
103+
104+ if ( allocation != 0 )
105+ return 0;
106+ else
107+ return 1;
108+}
109+
110+static int
111+freeMemory(void)
112+{
113+ free(allocation);
114+ return 0;
115+}
116+
117+static int
118+protectBelow(void)
119+{
120+ EF_PROTECT_BELOW = 1;
121+ return 0;
122+}
123+
124+static int
125+read0(void)
126+{
127+ c = *allocation;
128+
129+ return 0;
130+}
131+
132+static int
133+write0(void)
134+{
135+ *allocation = 1;
136+
137+ return 0;
138+}
139+
140+static int
141+read1(void)
142+{
143+ c = allocation[1];
144+
145+ return 0;
146+}
147+
148+static int
149+readMinus1(void)
150+{
151+ c = allocation[-1];
152+ return 0;
153+}
154+
155+static struct diagnostic diagnostics[] = {
156+ {
157+ testSizes, 0,
158+ "Please add -DLONG_LONG to the compiler flags and recompile."
159+ },
160+ {
161+ allocateMemory, 0,
162+ "Allocation 1: This test allocates a single byte of memory."
163+ },
164+ {
165+ read0, 0,
166+ "Read valid memory 1: This test reads the allocated memory."
167+ },
168+ {
169+ write0, 0,
170+ "Write valid memory 1: This test writes the allocated memory."
171+ },
172+ {
173+ read1, 1,
174+ "Read overrun: This test reads beyond the end of the buffer."
175+ },
176+ {
177+ freeMemory, 0,
178+ "Free memory: This test frees the allocated memory."
179+ },
180+ {
181+ protectBelow, 0,
182+ "Protect below: This sets Electric Fence to protect\n"
183+ "the lower boundary of a malloc buffer, rather than the\n"
184+ "upper boundary."
185+ },
186+ {
187+ allocateMemory, 0,
188+ "Allocation 2: This allocates memory with the lower boundary"
189+ " protected."
190+ },
191+ {
192+ read0, 0,
193+ "Read valid memory 2: This test reads the allocated memory."
194+ },
195+ {
196+ write0, 0,
197+ "Write valid memory 2: This test writes the allocated memory."
198+ },
199+ {
200+ readMinus1, 1,
201+ "Read underrun: This test reads before the beginning of the"
202+ " buffer."
203+ },
204+ {
205+ 0, 0, 0
206+ }
207+};
208+
209+static const char failedTest[]
210+ = "Electric Fence confidence test failed.\n";
211+
212+static const char newline = '\n';
213+
214+int
215+main(int argc, char * * argv)
216+{
217+ static const struct diagnostic * diag = diagnostics;
218+
219+
220+ EF_PROTECT_BELOW = 0;
221+ EF_ALIGNMENT = 0;
222+
223+ while ( diag->explanation != 0 ) {
224+ int status = gotSegmentationFault(diag->test);
225+
226+ if ( status != diag->expectedStatus ) {
227+ /*
228+ * Don't use stdio to print here, because stdio
229+ * uses malloc() and we've just proven that malloc()
230+ * is broken. Also, use _exit() instead of exit(),
231+ * because _exit() doesn't flush stdio.
232+ */
233+ write(2, failedTest, sizeof(failedTest) - 1);
234+ write(2, diag->explanation, strlen(diag->explanation));
235+ write(2, &newline, 1);
236+ _exit(-1);
237+ }
238+ diag++;
239+ }
240+ return 0;
241+}
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/libefence.3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/libefence.3 Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,415 @@
1+.TH efence 3 27-April-1993
2+.SH NAME
3+efence \- Electric Fence Malloc Debugger
4+.SH SYNOPSIS
5+.nf
6+.ft B
7+#include <stdlib.h>
8+.ft
9+.fi
10+.LP
11+.nf
12+.ft B
13+void * malloc (size_t size);
14+.ft
15+.fi
16+.LP
17+.nf
18+.ft B
19+void free (void *ptr);
20+.ft
21+.fi
22+.LP
23+.nf
24+.ft B
25+void * realloc (void *ptr, size_t size);
26+.ft
27+.fi
28+.LP
29+.nf
30+.ft B
31+void * calloc (size_t nelem, size_t elsize);
32+.ft
33+.fi
34+.LP
35+.nf
36+.ft B
37+void * memalign (size_t alignment, size_t size);
38+.ft
39+.fi
40+.LP
41+.nf
42+.ft B
43+void * valloc (size_t size);
44+.ft
45+.fi
46+.LP
47+.nf
48+.ft B
49+extern int EF_DISABLE_BANNER;
50+.ft
51+.fi
52+.LP
53+.nf
54+.ft B
55+extern int EF_ALIGNMENT;
56+.ft
57+.fi
58+.LP
59+.nf
60+.ft B
61+extern int EF_PROTECT_BELOW;
62+.ft
63+.fi
64+.LP
65+.nf
66+.ft B
67+extern int EF_PROTECT_FREE;
68+.ft
69+.fi
70+.LP
71+.nf
72+.ft B
73+extern int EF_ALLOW_MALLOC_0;
74+.ft
75+.fi
76+.LP
77+.nf
78+.ft B
79+extern int EF_FREE_WIPES;
80+.ft
81+.fi
82+.SH DESCRIPTION
83+.I Electric Fence
84+helps you detect two common programming bugs:
85+software that overruns the boundaries of a malloc() memory
86+allocation, and software that touches a memory allocation that has been
87+released by free(). Unlike other malloc() debuggers, Electric Fence will
88+detect
89+.I read
90+accesses as well as writes, and it will pinpoint the exact instruction that
91+causes an error. It has been in use at Pixar since 1987, and at many other
92+sites for years.
93+.LP
94+Electric Fence uses the virtual memory hardware of your computer to place an
95+inaccessible memory page immediately after (or before, at the user's option)
96+each memory allocation. When software reads or writes this inaccessible page,
97+the
98+hardware issues a segmentation fault, stopping the program at the offending
99+instruction. It is then trivial to find the erroneous statement using your
100+favorite debugger. In a similar manner, memory that has been released by
101+free() is made inaccessible, and any code that touches it will get a
102+segmentation fault.
103+.LP
104+Simply linking your application with libefence.a will allow you to detect
105+most, but not all, malloc buffer overruns and accesses of free memory.
106+If you want to be reasonably sure that you've found
107+.I all
108+bugs of this type, you'll have to read and understand the rest of this
109+man page.
110+.SH USAGE
111+Link your program with the library
112+.B libefence.a .
113+Make sure you are
114+.I not
115+linking with
116+.B -lmalloc,
117+.B -lmallocdebug,
118+or with other malloc-debugger or malloc-enhancer libraries.
119+You can only use one at a time.
120+If your system administrator
121+has installed Electric Fence for public use, you'll be able to use the
122+.B -lefence
123+argument to the linker, otherwise you'll have to put the path-name for
124+.B libefence.a
125+in the linker's command line.
126+Some systems will require special arguments to the linker to assure that
127+you are using the Electric Fence malloc() and not the one from your C library.
128+On AIX systems, you may have to use the flags
129+.br
130+.B -bnso
131+.B -bnodelcsect
132+.B -bI:/lib/syscalls.exp
133+.br
134+On Sun systems running SunOS 4.X, you'll probably have to use
135+.B -Bstatic.
136+.LP
137+Run your program
138+.I using a debugger.
139+It's easier to work this way than to create a
140+.B core
141+file and post-mortem debug it. Electric Fence can create
142+.I huge
143+core files, and some operating systems will thus take minutes simply to dump
144+core! Some operating systems will not create usable core files from programs
145+that are linked with Electric Fence.
146+If your program has one of the errors detected by Electric Fence, it will
147+get a segmentation fault (SIGSEGV) at the offending instruction. Use the
148+debugger to locate the erroneous statement, and repair it.
149+.SH GLOBAL AND ENVIRONMENT VARIABLES
150+Electric Fence has six configuration switches that can be enabled via
151+the shell environment, or by setting the value of global integer variables
152+using a debugger. These switches change what bugs Electric Fence will detect,
153+so it's important that you know how to use them.
154+.TP
155+EF_DISABLE_BANNER
156+This is an integer which if nonzero specifies that the usual Electric
157+Fence banner and copyright notice should not be printed. This is
158+provided for certain circumstances where the banner can be annoying
159+(eg, running a regression test suite that also monitors stderr). Note
160+that you should almost certainly not set this in your program, because
161+then you might leave Electric Fence linked into the production
162+version, which would be very bad.
163+.TP
164+EF_ALIGNMENT
165+This is an integer that specifies the alignment for any memory allocations
166+that will be returned by malloc(), calloc(), and realloc().
167+The value is specified in
168+bytes, thus a value of 4 will cause memory to be aligned to 32-bit boundaries
169+unless your system doesn't have a 8-bit characters. EF_ALIGNMENT is set to
170+sizeof(int) by default, since that is generally the word-size of your CPU.
171+If your program requires that allocations be aligned to 64-bit
172+boundaries and you have a 32-bit
173+.B int
174+you'll have to set this value to 8. This is the case when compiling with the
175+.B -mips2
176+flag on MIPS-based systems such as those from SGI.
177+The memory allocation that is returned by Electric Fence malloc() is aligned
178+using the value in EF_ALIGNMENT, and
179+.I its size the multiple of
180+.I that value
181+that is greater than or equal to the requested size.
182+For this reason, you will sometimes want to set EF_ALIGNMENT to 0 (no
183+alignment), so that
184+you can detect overruns of less than your CPU's word size. Be sure to read
185+the section
186+.I WORD-ALIGNMENT AND OVERRUN DETECTION
187+in this manual page before you try this.
188+To change this value, set EF_ALIGNMENT in the shell environment to an
189+integer value, or assign
190+to the global integer variable EF_ALIGNMENT using a debugger.
191+.TP
192+EF_PROTECT_BELOW
193+Electric Fence usually places an inaccessible page immediately after each
194+memory allocation, so that software that runs past the end of the allocation
195+will be detected. Setting EF_PROTECT_BELOW to 1 causes Electric Fence
196+to place the inaccessible page
197+.I before
198+the allocation in the address space, so that under-runs will be detected
199+instead of over-runs.
200+When EF_PROTECT_BELOW is set, the EF_ALIGNMENT parameter is ignored.
201+All allocations will be aligned to virtual-memory-page boundaries, and
202+their size will be the exact size that was requested.
203+To change this value, set EF_PROTECT_BELOW in the shell environment to an
204+integer value, or assign to the global integer variable EF_PROTECT_BELOW using
205+a debugger.
206+.TP
207+EF_PROTECT_FREE
208+When EF_PROTECT_FREE is not set (i. e. set to 0), Electric Fence returns free
209+memory to a pool and only checks accesses to it until it is reallocated. If
210+you suspect that a program may be touching free memory, set EF_PROTECT_FREE to
211+1. This will cause Electric Fence to never re-allocate memory once it has been
212+freed, so that any access to free memory will be detected. Some programs will
213+use tremendous amounts of memory when this parameter is set. To change this
214+value, set EF_PROTECT_FREE in the shell environment to an integer value, or
215+assign to the global integer variable EF_PROTECT_FREE using a debugger.
216+.TP
217+EF_ALLOW_MALLOC_0
218+By default, Electric Fence traps calls to malloc() with a size of zero, because
219+they are often the result of a software bug. If EF_ALLOW_MALLOC_0 is non-zero,
220+the software will not trap calls to malloc() with a size of zero.
221+To change this value, set EF_ALLOW_MALLOC_0 in the shell environment to an
222+integer value, or assign to the global integer variable EF_ALLOW_MALLOC_0 using
223+a debugger.
224+.TP
225+EF_FREE_WIPES
226+By default, Electric Fence releases memory without changing the content
227+of the released memory block. IF EF_FREE_WIPES is non-zero, the sofware
228+will fill the memory block with 0xbd values before it is released.
229+This makes it easier to trigger illegal use of released memory, and eaiser
230+to understand why a memory access failed during gdb runs.
231+.SH WORD-ALIGNMENT AND OVERRUN DETECTION
232+There is a conflict between the alignment restrictions that malloc() operates
233+under and the debugging strategy used by Electric Fence. When detecting
234+overruns, Electric Fence malloc() allocates two or more virtual memory
235+pages for each allocation. The last page is made inaccessible in such a way
236+that any read, write, or execute access will cause a segmentation fault.
237+Then, Electric Fence malloc() will return an address such that the first
238+byte after
239+the end of the allocation is on the inaccessible page.
240+Thus, any overrun
241+of the allocation will cause a segmentation fault.
242+.LP
243+It follows that the
244+address returned by malloc() is the address of the inaccessible page minus
245+the size of the memory allocation.
246+Unfortunately, malloc() is required to return
247+.I word-aligned
248+allocations, since many CPUs can only access a word when its address is aligned.
249+The conflict happens when software makes a memory allocation using a size that
250+is not a multiple of the word size, and expects to do word accesses to that
251+allocation. The location of the inaccessible page is fixed by hardware at
252+a word-aligned address. If Electric Fence malloc() is to return an aligned
253+address, it must increase the size of the allocation to a multiple of the
254+word size.
255+In addition, the functions memalign() and valloc() must honor explicit
256+specifications on the alignment of the memory allocation, and this, as well
257+can only be implemented by increasing the size of the allocation.
258+Thus, there will be situations in which the end of a memory allocation
259+contains some padding space, and accesses of that padding space will not
260+be detected, even if they are overruns.
261+.LP
262+Electric Fence provides the variable EF_ALIGNMENT so that the user can
263+control the default alignment used by malloc(), calloc(), and realloc().
264+To debug overruns as small as a single byte, you can set EF_ALIGNMENT to
265+zero. This will result in Electric Fence malloc() returning unaligned
266+addresses for allocations with sizes that are not a multiple of the word
267+size. This is not a problem in most cases, because compilers must pad the
268+size of objects so that alignment restrictions are honored when storing
269+those objects in arrays. The problem surfaces when software allocates
270+odd-sized buffers for objects that must be word-aligned. One case of this
271+is software that allocates a buffer to contain a structure and a
272+string, and the string has an odd size (this example was in a popular TIFF
273+library). If word references are made to un-aligned buffers, you will see
274+a bus error (SIGBUS) instead of a segmentation fault. The only way to fix
275+this is to re-write the offending code to make byte references or not make
276+odd-sized allocations, or to set EF_ALIGNMENT to the word size.
277+.LP
278+Another example of software incompatible with
279+EF_ALIGNMENT < word-size
280+is the strcmp() function and other string functions on SunOS (and probably
281+Solaris), which make word-sized accesses to character strings, and may
282+attempt to access up to three bytes beyond the end of a string. These
283+result in a segmentation fault (SIGSEGV). The only way around this is to
284+use versions of the string functions that perform byte references instead
285+of word references.
286+.SH INSTRUCTIONS FOR DEBUGGING YOUR PROGRAM
287+.TP
288+1.
289+Link with libefence.a as explained above.
290+.TP
291+2.
292+Run your program in a debugger and fix any overruns or accesses to free memory.
293+.TP
294+3.
295+Quit the debugger.
296+.TP
297+4.
298+Set EF_PROTECT_BELOW = 1 in the shell environment.
299+.TP
300+5.
301+Repeat step 2, this time repairing underruns if they occur.
302+.TP
303+6.
304+Quit the debugger.
305+.TP
306+7.
307+Read the restrictions in the section on
308+.I WORD-ALIGNMENT AND OVERRUN DETECTION.
309+See if you can
310+set EF_ALIGNMENT to 0 and repeat step 2. Sometimes this will be too much work,
311+or there will be problems with library routines for which you don't have the
312+source, that will prevent you from doing this.
313+.SH MEMORY USAGE AND EXECUTION SPEED
314+Since Electric Fence uses at least two virtual memory pages for each of its
315+allocations, it's a terrible memory hog. I've sometimes found it necessary to
316+add a swap file using swapon(8) so that the system would have enough virtual
317+memory to debug my program. Also, the way we manipulate memory results in
318+various cache and translation buffer entries being flushed with each call
319+to malloc or free. The end result is that your program will be much slower
320+and use more resources while you are debugging it with Electric Fence.
321+.LP
322+Don't leave libefence.a linked into production software! Use it only
323+for debugging.
324+.SH PORTING
325+Electric Fence is written for ANSI C. You should be able to port it with
326+simple changes to the Makefile and to page.c,
327+which contains the memory management primitives .
328+Many POSIX platforms will require only a re-compile.
329+The operating system facilities required to port Electric Fence are:
330+.IP
331+A way to allocate memory pages
332+.br
333+A way to make selected pages inaccessible.
334+.br
335+A way to make the pages accessible again.
336+.br
337+A way to detect when a program touches an inaccessible page.
338+.br
339+A way to print messages.
340+.LP
341+Please e-mail me a copy of any changes you have to make, so that I can
342+merge them into the distribution.
343+.SH AUTHOR
344+Bruce Perens
345+.SH WARNINGS
346+I have tried to do as good a job as I can on this software, but I doubt
347+that it is even theoretically possible to make it bug-free.
348+This software has no warranty. It will not detect some bugs that you might
349+expect it to detect, and will indicate that some non-bugs are bugs.
350+Bruce Perens and/or Pixar will not be liable to any claims resulting
351+from the use of this software or the ideas within it.
352+The entire responsibility for its use must
353+be assumed by the user. If you use it and it results in loss of life
354+and/or property, tough. If it leads you on a wild goose chase and you waste
355+two weeks debugging something, too bad.
356+If you can't deal with the above, please don't use the software! I've written
357+this in an attempt to help other people, not to get myself sued or prosecuted.
358+.SH LICENSE
359+Copyright 1987-1995 Bruce Perens. All rights reserved.
360+.br
361+This program is free software; you can redistribute it and/or modify
362+it under the terms of the GNU General Public License, Version 2,
363+as published by the Free Software Foundation. A copy of this license is
364+distributed with this software in the file "COPYING".
365+
366+This program is distributed in the hope that it will be useful,
367+but WITHOUT ANY WARRANTY; without even the implied warranty of
368+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Read the
369+file "COPYING" for more details.
370+.SH CONTACTING THE AUTHOR
371+.nf
372+Bruce Perens
373+c/o Pixar
374+1001 West Cutting Blvd., Suite 200
375+Richmond, CA 94804
376+
377+Telephone: 510-215-3502
378+Fax: 510-236-0388
379+Internet: Bruce@Pixar.com
380+.fi
381+.ft
382+.SH FILES
383+/dev/zero: Source of memory pages (via mmap(2)).
384+.SH SEE ALSO
385+malloc(3), mmap(2), mprotect(2), swapon(8)
386+.SH DIAGNOSTICS
387+Segmentation Fault: Examine the offending statement for violation of the
388+boundaries of a memory allocation.
389+.br
390+Bus Error: See the section on
391+.I WORD-ALIGNMENT AND OVERRUN DETECTION.
392+in this manual page.
393+.SH BUGS
394+My explanation of the alignment issue could be improved.
395+.LP
396+Some Sun systems running SunOS 4.1 are reported to signal an access to a
397+protected page with
398+.B SIGBUS
399+rather than
400+.B SIGSEGV,
401+I suspect this is an undocumented feature of a particular Sun hardware
402+version, not just the operating system.
403+On these systems, eftest will fail with a bus error until you modify the
404+Makefile to define
405+.B PAGE_PROTECTION_VIOLATED_SIGNAL
406+as
407+.B SIGBUS.
408+.LP
409+There are, without doubt, other bugs and porting issues. Please contact me via
410+e-mail if you have any bug reports, ideas, etc.
411+.SH WHAT'S BETTER
412+PURIFY, from Purify Systems, does a much better job than Electric Fence, and
413+does much more. It's available at this writing on SPARC and HP.
414+I'm not affiliated with Purify, I just think it's a wonderful product
415+and you should check it out.
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/page-win32.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/page-win32.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,124 @@
1+#include "efence.h"
2+#include <stdlib.h>
3+#include <stdio.h>
4+#include <string.h>
5+
6+static caddr_t startAddr = (caddr_t) 0;
7+
8+
9+/* TODO: This function is not thread safe. */
10+static const char *
11+stringErrorReport(void)
12+{
13+ static char buf[1024];
14+ DWORD err = GetLastError();
15+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | 78, NULL, err, 0, buf, sizeof(buf), NULL);
16+
17+ buf[sizeof(buf)-1] = 0;
18+ return buf;
19+}
20+
21+/*
22+ * Create memory.
23+ */
24+void *
25+Page_Create(size_t size)
26+{
27+ caddr_t allocation;
28+
29+ /*
30+ * In this version, "startAddr" is a _hint_, not a demand.
31+ * When the memory I map here is contiguous with other
32+ * mappings, the allocator can coalesce the memory from two
33+ * or more mappings into one large contiguous chunk, and thus
34+ * might be able to find a fit that would not otherwise have
35+ * been possible. I could _force_ it to be contiguous by using
36+ * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
37+ * generated by other software, etc.
38+ */
39+ allocation = (caddr_t) VirtualAlloc(
40+ (LPVOID)startAddr
41+ ,size
42+ ,MEM_RESERVE|MEM_COMMIT
43+ ,PAGE_READWRITE);
44+
45+#ifndef _WIN32
46+ /*
47+ * Set the "address hint" for the next mmap() so that it will abut
48+ * the mapping we just created.
49+ *
50+ * Windows doesn't treat the address as a hint.
51+ *
52+ * Maybe TODO: Hint and retry when the hint fails.
53+ */
54+ startAddr = allocation + size;
55+#endif
56+
57+ if ( allocation == 0 )
58+ EF_Exit("VirtualAlloc() failed: %s", stringErrorReport());
59+
60+ return (void *)allocation;
61+}
62+
63+static DWORD AllocationGranularity;
64+
65+static void
66+mprotectFailed(void)
67+{
68+ EF_Exit("VirtualProtect() failed: %s", stringErrorReport());
69+}
70+
71+/* Win32's VirtualProtect does not work across VirtualAlloc boundaries */
72+/* Therefore, avoid the problem by doing all operations in AllocationGranularity sized chunks */
73+
74+void
75+Page_AllowAccess(void * address, size_t size)
76+{
77+ DWORD old;
78+ while (size) {
79+ size_t mySize;
80+ mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
81+ if (!VirtualProtect(address, mySize, PAGE_READWRITE, &old))
82+ mprotectFailed();
83+ size -= mySize;
84+ address = (void *)((DWORD_PTR)address + mySize);
85+ }
86+}
87+
88+void
89+Page_DenyAccess(void * address, size_t size)
90+{
91+ DWORD old;
92+ while (size) {
93+ size_t mySize;
94+ mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
95+ if (!VirtualProtect(address, mySize, PAGE_NOACCESS, &old))
96+ mprotectFailed();
97+ size -= mySize;
98+ address = (void *)((DWORD_PTR)address + mySize);
99+ }
100+}
101+
102+void
103+Page_Delete(void * address, size_t size)
104+{
105+// Page_DenyAccess(address, size);
106+ while (size) {
107+ size_t mySize;
108+ mySize = min(size, AllocationGranularity - ((DWORD_PTR)address) % AllocationGranularity);
109+ if (!VirtualFree(address, mySize, MEM_DECOMMIT))
110+ EF_Exit("VirtualFree() failed: %s", stringErrorReport());
111+ size -= mySize;
112+ address = (void *)((DWORD_PTR)address + mySize);
113+ }
114+}
115+
116+size_t
117+Page_Size(void)
118+{
119+ SYSTEM_INFO info;
120+
121+ GetSystemInfo(&info);
122+ AllocationGranularity = info.dwAllocationGranularity;
123+ return info.dwPageSize;
124+}
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/page.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/page.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,185 @@
1+#include "efence.h"
2+#include <stdlib.h>
3+#include <unistd.h>
4+#include <fcntl.h>
5+#include <sys/mman.h>
6+#include <stdio.h>
7+#include <errno.h>
8+#include <string.h>
9+
10+/*
11+ * Lots of systems are missing the definition of PROT_NONE.
12+ */
13+#ifndef PROT_NONE
14+#define PROT_NONE 0
15+#endif
16+
17+/*
18+ * 386 BSD has MAP_ANON instead of MAP_ANONYMOUS.
19+ */
20+#if ( !defined(MAP_ANONYMOUS) && defined(MAP_ANON) )
21+#define MAP_ANONYMOUS MAP_ANON
22+#endif
23+
24+/*
25+ * For some reason, I can't find mprotect() in any of the headers on
26+ * IRIX or SunOS 4.1.2
27+ */
28+/* extern C_LINKAGE int mprotect(void * addr, size_t len, int prot); */
29+
30+static caddr_t startAddr = (caddr_t) 0;
31+
32+#if ( !defined(sgi) && !defined(_AIX) )
33+extern int sys_nerr;
34+/*extern char * sys_errlist[];*/
35+#endif
36+
37+static const char *
38+stringErrorReport(void)
39+{
40+#if ( defined(sgi) )
41+ return strerror(oserror());
42+#elif ( defined(_AIX) )
43+ return strerror(errno);
44+#else
45+ if ( errno > 0 && errno < sys_nerr )
46+ return sys_errlist[errno];
47+ else
48+ return "Unknown error.\n";
49+#endif
50+}
51+
52+/*
53+ * Create memory.
54+ */
55+#if defined(MAP_ANONYMOUS)
56+void *
57+Page_Create(size_t size)
58+{
59+ caddr_t allocation;
60+
61+ /*
62+ * In this version, "startAddr" is a _hint_, not a demand.
63+ * When the memory I map here is contiguous with other
64+ * mappings, the allocator can coalesce the memory from two
65+ * or more mappings into one large contiguous chunk, and thus
66+ * might be able to find a fit that would not otherwise have
67+ * been possible. I could _force_ it to be contiguous by using
68+ * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
69+ * generated by other software, etc.
70+ */
71+ allocation = (caddr_t) mmap(
72+ startAddr
73+ ,size
74+ ,PROT_READ|PROT_WRITE
75+ ,MAP_PRIVATE|MAP_ANONYMOUS
76+ ,-1
77+ ,0);
78+
79+#ifndef __hpux
80+ /*
81+ * Set the "address hint" for the next mmap() so that it will abut
82+ * the mapping we just created.
83+ *
84+ * HP/UX 9.01 has a kernel bug that makes mmap() fail sometimes
85+ * when given a non-zero address hint, so we'll leave the hint set
86+ * to zero on that system. HP recently told me this is now fixed.
87+ * Someone please tell me when it is probable to assume that most
88+ * of those systems that were running 9.01 have been upgraded.
89+ */
90+ startAddr = allocation + size;
91+#endif
92+
93+ if ( allocation == (caddr_t)-1 )
94+ EF_Exit("mmap() failed: %s", stringErrorReport());
95+
96+ return (void *)allocation;
97+}
98+#else
99+void *
100+Page_Create(size_t size)
101+{
102+ static int devZeroFd = -1;
103+ caddr_t allocation;
104+
105+ if ( devZeroFd == -1 ) {
106+ devZeroFd = open("/dev/zero", O_RDWR);
107+ if ( devZeroFd < 0 )
108+ EF_Exit(
109+ "open() on /dev/zero failed: %s"
110+ ,stringErrorReport());
111+ }
112+
113+ /*
114+ * In this version, "startAddr" is a _hint_, not a demand.
115+ * When the memory I map here is contiguous with other
116+ * mappings, the allocator can coalesce the memory from two
117+ * or more mappings into one large contiguous chunk, and thus
118+ * might be able to find a fit that would not otherwise have
119+ * been possible. I could _force_ it to be contiguous by using
120+ * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
121+ * generated by other software, etc.
122+ */
123+ allocation = (caddr_t) mmap(
124+ startAddr
125+ ,size
126+ ,PROT_READ|PROT_WRITE
127+ ,MAP_PRIVATE
128+ ,devZeroFd
129+ ,0);
130+
131+ startAddr = allocation + size;
132+
133+ if ( allocation == (caddr_t)-1 )
134+ EF_Exit("mmap() failed: %s", stringErrorReport());
135+
136+ return (void *)allocation;
137+}
138+#endif
139+
140+static void
141+mprotectFailed(void)
142+{
143+ EF_Exit("mprotect() failed: %s", stringErrorReport());
144+}
145+
146+void
147+Page_AllowAccess(void * address, size_t size)
148+{
149+ if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
150+ mprotectFailed();
151+}
152+
153+void
154+Page_DenyAccess(void * address, size_t size)
155+{
156+ if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
157+ mprotectFailed();
158+}
159+
160+void
161+Page_Delete(void * address, size_t size)
162+{
163+ Page_DenyAccess(address, size);
164+}
165+
166+#if defined(_SC_PAGESIZE)
167+size_t
168+Page_Size(void)
169+{
170+ return (size_t)sysconf(_SC_PAGESIZE);
171+}
172+#elif defined(_SC_PAGE_SIZE)
173+size_t
174+Page_Size(void)
175+{
176+ return (size_t)sysconf(_SC_PAGE_SIZE);
177+}
178+#else
179+/* extern int getpagesize(); */
180+size_t
181+Page_Size(void)
182+{
183+ return getpagesize();
184+}
185+#endif
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/print.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/print.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,189 @@
1+#include "efence.h"
2+#include <stdlib.h>
3+#ifndef _WIN32
4+#include <unistd.h>
5+#endif
6+#include <stdarg.h>
7+#include <string.h>
8+#include <signal.h>
9+
10+/*
11+ * These routines do their printing without using stdio. Stdio can't
12+ * be used because it calls malloc(). Internal routines of a malloc()
13+ * debugger should not re-enter malloc(), so stdio is out.
14+ */
15+
16+/*
17+ * NUMBER_BUFFER_SIZE is the longest character string that could be needed
18+ * to represent an unsigned integer, assuming we might print in base 2.
19+ */
20+#define NUMBER_BUFFER_SIZE (sizeof(ef_number) * NBBY)
21+
22+#ifdef _WIN32
23+void write(int fileno, char *buf, size_t size)
24+{
25+ char scratch[2] = { 0, 0 };
26+
27+ /* This will be insanely slow, but it should work with almost no memory overhead */
28+ while (size--) {
29+ scratch[0] = *buf++;
30+ OutputDebugString(scratch);
31+ }
32+}
33+#endif
34+
35+static void
36+printNumber(ef_number number, ef_number base)
37+{
38+ char buffer[NUMBER_BUFFER_SIZE];
39+ char * s = &buffer[NUMBER_BUFFER_SIZE];
40+ int size;
41+
42+ do {
43+ ef_number digit;
44+
45+ if ( --s == buffer )
46+ EF_Abort("Internal error printing number.");
47+
48+ digit = number % base;
49+
50+ if ( digit < 10 )
51+ *s = '0' + digit;
52+ else
53+ *s = 'a' + digit - 10;
54+
55+ } while ( (number /= base) > 0 );
56+
57+ size = &buffer[NUMBER_BUFFER_SIZE] - s;
58+
59+ if ( size > 0 )
60+ write(2, s, size);
61+}
62+
63+static void
64+vprint(const char * pattern, va_list args)
65+{
66+ static const char bad_pattern[] =
67+ "\nBad pattern specifier %%%c in EF_Print().\n";
68+ const char * s = pattern;
69+ char c;
70+
71+ while ( (c = *s++) != '\0' ) {
72+ if ( c == '%' ) {
73+ c = *s++;
74+ switch ( c ) {
75+ case '%':
76+ (void) write(2, &c, 1);
77+ break;
78+ case 'a':
79+ /*
80+ * Print an address passed as a void pointer.
81+ * The type of ef_number must be set so that
82+ * it is large enough to contain all of the
83+ * bits of a void pointer.
84+ */
85+ printNumber(
86+ (ef_number)va_arg(args, void *)
87+ ,0x10);
88+ break;
89+ case 's':
90+ {
91+ const char * string;
92+ size_t length;
93+
94+ string = va_arg(args, char *);
95+ length = strlen(string);
96+
97+ (void) write(2, string, length);
98+ }
99+ break;
100+ case 'd':
101+ {
102+ int n = va_arg(args, int);
103+
104+ if ( n < 0 ) {
105+ char c = '-';
106+ write(2, &c, 1);
107+ n = -n;
108+ }
109+ printNumber(n, 10);
110+ }
111+ break;
112+ case 'x':
113+ printNumber(va_arg(args, u_int), 0x10);
114+ break;
115+ case 'c':
116+ { /*Cast used, since char gets promoted to int in ... */
117+ char c = (char) va_arg(args, int);
118+
119+ (void) write(2, &c, 1);
120+ }
121+ break;
122+ default:
123+ {
124+ EF_Print(bad_pattern, c);
125+ }
126+
127+ }
128+ }
129+ else
130+ (void) write(2, &c, 1);
131+ }
132+}
133+
134+void
135+EF_Abort(const char * pattern, ...)
136+{
137+ va_list args;
138+
139+ va_start(args, pattern);
140+
141+ EF_Print("\nElectricFence Aborting: ");
142+ vprint(pattern, args);
143+ EF_Print("\n");
144+
145+ va_end(args);
146+
147+ /*
148+ * I use kill(getpid(), SIGILL) instead of abort() because some
149+ * mis-guided implementations of abort() flush stdio, which can
150+ * cause malloc() or free() to be called.
151+ */
152+#ifdef _WIN32
153+ ExitProcess(-1);
154+#else
155+ kill(getpid(), SIGILL);
156+#endif
157+ /* Just in case something handles SIGILL and returns, exit here. */
158+ _exit(-1);
159+}
160+
161+void
162+EF_Exit(const char * pattern, ...)
163+{
164+ va_list args;
165+
166+ va_start(args, pattern);
167+
168+ EF_Print("\nElectricFence Exiting: ");
169+ vprint(pattern, args);
170+ EF_Print("\n");
171+
172+ va_end(args);
173+
174+ /*
175+ * I use _exit() because the regular exit() flushes stdio,
176+ * which may cause malloc() or free() to be called.
177+ */
178+ _exit(-1);
179+}
180+
181+void
182+EF_Print(const char * pattern, ...)
183+{
184+ va_list args;
185+
186+ va_start(args, pattern);
187+ vprint(pattern, args);
188+ va_end(args);
189+}
diff -r beef8a621eb3 -r 7b00b56bfbf3 efence/tstheap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/efence/tstheap.c Sat Jul 04 06:11:41 2020 -0400
@@ -0,0 +1,74 @@
1+#include <stdlib.h>
2+#include <stdio.h>
3+#include <math.h>
4+#include <limits.h>
5+#include "efence.h"
6+
7+/*
8+ * This is a simple program to exercise the allocator. It allocates and frees
9+ * memory in a pseudo-random fashion. It should run silently, using up time
10+ * and resources on your system until you stop it or until it has gone
11+ * through TEST_DURATION (or the argument) iterations of the loop.
12+ */
13+
14+extern C_LINKAGE double drand48(void); /* For pre-ANSI C systems */
15+
16+#define POOL_SIZE 1024
17+#define LARGEST_BUFFER 30000
18+#define TEST_DURATION 1000000
19+
20+void * pool[POOL_SIZE];
21+
22+#ifdef _WIN32
23+double
24+drand48(void)
25+{
26+ double rv;
27+
28+ rv = rand() * (double)RAND_MAX + rand();
29+ rv /= (double)RAND_MAX * RAND_MAX;
30+
31+ return rv;
32+}
33+#else
34+#ifdef FAKE_DRAND48
35+/*
36+ * Add -DFAKE_DRAND48 to your compile flags if your system doesn't
37+ * provide drand48().
38+ */
39+
40+#ifndef ULONG_MAX
41+#define ULONG_MAX ~(1L)
42+#endif
43+
44+double
45+drand48(void)
46+{
47+ return (random() / (double)ULONG_MAX);
48+}
49+#endif
50+#endif
51+
52+int
53+main(int argc, char * * argv)
54+{
55+ int count = 0;
56+ int duration = TEST_DURATION;
57+
58+ if ( argc >= 2 )
59+ duration = atoi(argv[1]);
60+
61+ for ( ; count < duration; count++ ) {
62+ void * * element = &pool[(int)(drand48() * POOL_SIZE)];
63+ size_t size = (size_t)(drand48() * (LARGEST_BUFFER + 1));
64+
65+ if ( *element ) {
66+ free( *element );
67+ *element = 0;
68+ }
69+ else if ( size > 0 ) {
70+ *element = malloc(size);
71+ }
72+ }
73+ return 0;
74+}
Show on old repository browser