]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Many files:
authorHarlan Stenn <stenn@ntp.org>
Thu, 13 Jul 2000 21:57:59 +0000 (21:57 -0000)
committerHarlan Stenn <stenn@ntp.org>
Thu, 13 Jul 2000 21:57:59 +0000 (21:57 -0000)
  * configure.in (AC_CONFIG_FILES): Added ElectricFence/Makefile
  * ElectricFence: Imporpted.

bk: 396e3b67GkAAj1vXuk5j5HkiUAxfpA

16 files changed:
ChangeLog
ElectricFence/CHANGES [new file with mode: 0644]
ElectricFence/COPYING [new file with mode: 0644]
ElectricFence/Makefile- [new file with mode: 0644]
ElectricFence/Makefile.am [new file with mode: 0644]
ElectricFence/Makefile.in [new file with mode: 0644]
ElectricFence/README [new file with mode: 0644]
ElectricFence/efence.c [new file with mode: 0644]
ElectricFence/efence.h [new file with mode: 0644]
ElectricFence/eftest.c [new file with mode: 0644]
ElectricFence/libefence.3 [new file with mode: 0644]
ElectricFence/page.c [new file with mode: 0644]
ElectricFence/print.c [new file with mode: 0644]
ElectricFence/tstheap.c [new file with mode: 0644]
configure
configure.in

index b180b7fe4e5bfeb4ab41618a0275bc9cd8a9f1cf..068a7a0be30b05aeefcb61fb4381445355b4c651 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2000-07-13  Harlan Stenn  <stenn@whimsy.udel.edu>
+
+       * configure.in (AC_CONFIG_FILES): Added ElectricFence/Makefile
+       * ElectricFence: Imporpted.
+
+2000-07-12  Harlan Stenn  <stenn@whimsy.udel.edu>
+
+       * util/ntp_genkeys.c (main): Cleanup
+       * ntpd/refclock_wwv.c (wwv_qrz): sqrt -> SQRT
+       * ntpd/refclock_chu.c (chu_rf): sqrt -> SQRT
+       * ntpd/ntpd.c (set_process_priority): Disable  high-priority for now.
+       PUBKEY cleanup.
+       * ntpd/ntp_timer.c: sys_revoketime cleanup.
+       * ntpd/ntp_proto.c (receive): PUBKEY cleanup.  Comment and code
+       cleanup.
+       (process_packet): Comment and code (PUBKEY) cleanup.
+       (peer_xmit): Comment and code cleanup.
+       (fast_xmit): Comment and code cleanup.
+       * ntpd/ntp_peer.c (expire_all): revoketime cleanup.  PUBKEY cleanup.
+       * ntpd/ntp_crypto.c: Comment reorg.  DH parameters are now
+       file-static instead of local to subroutines.
+       (make_keylist): peer->pcookie.key cleanup/fix
+       (crypto_recv): Subroutine documentation cleanup, other cleanup
+       (crypto_xmit): Cleanup/document.
+       (crypto_setup): Cleanup/document.
+       (crypto_agree): Cleanup/document.
+       (crypto_rsa): now static
+       (crypto_dh): now static.  Comment cleanup.  Code cleanup.
+       (crypto_tai): now static.  Code and comment cleanup.
+       (crypto_config): Deal with CRYPTO_CONF_LEAP.
+       * ntpd/ntp_control.c (CS_DHPARAMS): Rename corresponding token to
+       "params".  Remove CS_TAI from def_sys_var[].
+       (ctl_putsys): CS_HOST, CS_DHPARAMSm CS_REVTIME, and CS_LEAPTIME
+       bugfix.  CS_TAI cleanup.
+       * ntpd/ntp_config.c (CONF_CRYPTO_LEAP): Added
+       (getconfig): Added CONF_CRYPTO_LEAP support.
+       * include/ntp_syslog.h: Lose GIZMO stuff.
+       * include/ntp_crypto.h (CRYPTO_CONF_LEAP): Added
+       * include/ntp.h: struct autokey, cookie,value, and pkt changes for
+       signature field.  Update the inline docs on pkt's exten field.
+       From: Dave Mills
+       
+
 2000-07-08  Harlan Stenn  <stenn@whimsy.udel.edu>
 
        * ntpd/ntp_util.c (stats_config): If we read a bogus old_drift,
diff --git a/ElectricFence/CHANGES b/ElectricFence/CHANGES
new file mode 100644 (file)
index 0000000..454aff6
--- /dev/null
@@ -0,0 +1,23 @@
+2.0.1
+       Add work-arounds for kernel and library bugs under HP-UX.       
+       HP has been notified and will repair these soon.
+
+2.0.2
+       Add support for DEC Alpha. Add %a pattern for printing addresses, which
+       assumes they are passed in a void *.
+
+2.0.3 30-Sep-1993
+       When realloc is passed a zero address, it should work the same
+       way as malloc(). Fix forward declaration of mprotect() in page.c to
+       use void *, not caddr_t, for addresses. IRIX 5.0.1 complained about that.
+
+2.0.4 29-May-1994
+       Don't attempt to allow access to a zero-sized page when
+       EF_ALLOW_MALLOC_0 is set. Attempt to un-map memory from
+       Page_Delete(). If that doesn't work, fall back by protecting the
+       page from all references. Un-mapping small segments of a mapping
+       used to crash my SGI IRIX 5.0 system. I assume that nobody is running
+       5.0 any longer.
+
+2.0.5 20-January-1995
+       Port to Linux.
diff --git a/ElectricFence/COPYING b/ElectricFence/COPYING
new file mode 100644 (file)
index 0000000..a43ea21
--- /dev/null
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+       Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ElectricFence/Makefile- b/ElectricFence/Makefile-
new file mode 100644 (file)
index 0000000..0ce8c05
--- /dev/null
@@ -0,0 +1,72 @@
+ASFLAGS= -mips2
+CC= cc
+AR= ar
+INSTALL= install
+MV= mv
+CHMOD= chmod
+CFLAGS= -g
+LIB_INSTALL_DIR= /usr/lib
+MAN_INSTALL_DIR= /usr/man/man3
+
+PACKAGE_SOURCE= README libefence.3 Makefile efence.h \
+       efence.c page.c print.c eftest.c tstheap.c CHANGES
+
+# Un-comment the following if you are running HP/UX.
+# CFLAGS= -Aa -g -D_HPUX_SOURCE -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+# Un-comment the following if you are running AIX. This makes sure you won't
+# get the shared-library malloc() rather than the Electric Fence malloc().
+# COMPILE THE PROGRAMS YOU ARE DEBUGGING WITH THESE FLAGS, TOO.
+# CFLAGS= -g -bnso -bnodelcsect -bI:/lib/syscalls.exp
+
+# Un-comment the following if you are running SunOS 4.X
+# Note the definition of PAGE_PROTECTION_VIOLATED_SIGNAL. This may vary
+# depend on what version of Sun hardware you have.
+# You'll probably have to link the program you are debugging with -Bstatic
+# as well if using Sun's compiler, -static if using GCC.
+# CFLAGS= -g -Bstatic -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+OBJECTS= efence.o page.o print.o
+
+all:   libefence.a tstheap eftest
+       @ echo
+       @ echo "Testing Electric Fence."
+       @ echo "After the last test, it should print that the test has PASSED."
+       ./eftest
+       ./tstheap 3072
+       @ echo
+       @ echo "Electric Fence confidence test PASSED." 
+       @ echo
+
+install: libefence.a libefence.3
+       $(MV) libefence.a $(LIB_INSTALL_DIR)
+       $(CHMOD) 644 $(LIB_INSTALL_DIR)/libefence.a
+       $(INSTALL) libefence.3 $(MAN_INSTALL_DIR)/libefence.3
+       $(CHMOD) 644 $(MAN_INSTALL_DIR)/libefence.3
+
+clean:
+       - rm -f $(OBJECTS) tstheap.o eftest.o tstheap eftest libefence.a \
+        libefence.cat ElectricFence.shar
+
+roff:
+       nroff -man < libefence.3 > libefence.cat
+
+
+ElectricFence.shar: $(PACKAGE_SOURCE)
+       shar $(PACKAGE_SOURCE) > ElectricFence.shar
+
+shar: ElectricFence.shar
+
+libefence.a: $(OBJECTS)
+       - rm -f libefence.a
+       $(AR) crv libefence.a $(OBJECTS)
+
+tstheap: libefence.a tstheap.o
+       - rm -f tstheap
+       $(CC) $(CFLAGS) tstheap.o libefence.a -o tstheap
+
+eftest: libefence.a eftest.o
+       - rm -f eftest
+       $(CC) $(CFLAGS) eftest.o libefence.a -o eftest
+
+$(OBJECTS) tstheap.o eftest.o: efence.h
diff --git a/ElectricFence/Makefile.am b/ElectricFence/Makefile.am
new file mode 100644 (file)
index 0000000..8b3c961
--- /dev/null
@@ -0,0 +1,29 @@
+# Harlan Stenn <stenn@whimsy.udel.edu>
+# Converted the original Makefile (now in Makefile-) to Makefile.am
+# in July of '00
+
+EXTRA_DIST = libefence.3 CHANGES
+libefence_a_SOURCES = efence.h efence.c page.c print.c
+check_PROGRAMS = eftest tstheap
+# TESTS = eftest tstheap
+noinst_LIBRARIES = libefence.a
+LDADD = libefence.a
+
+# Un-comment the following if you are running HP/UX.
+# CFLAGS= -Aa -g -D_HPUX_SOURCE -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+# Un-comment the following if you are running AIX. This makes sure you won't
+# get the shared-library malloc() rather than the Electric Fence malloc().
+# COMPILE THE PROGRAMS YOU ARE DEBUGGING WITH THESE FLAGS, TOO.
+# CFLAGS= -g -bnso -bnodelcsect -bI:/lib/syscalls.exp
+
+# Un-comment the following if you are running SunOS 4.X
+# Note the definition of PAGE_PROTECTION_VIOLATED_SIGNAL. This may vary
+# depend on what version of Sun hardware you have.
+# You'll probably have to link the program you are debugging with -Bstatic
+# as well if using Sun's compiler, -static if using GCC.
+# CFLAGS= -g -Bstatic -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+check-local:
+       ./eftest
+       ./tstheap 3072
diff --git a/ElectricFence/Makefile.in b/ElectricFence/Makefile.in
new file mode 100644 (file)
index 0000000..8ae4c49
--- /dev/null
@@ -0,0 +1,376 @@
+# Makefile.in generated automatically by automake 1.4a from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_FLAG =
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+
+@SET_MAKE@
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMDEP = @AMDEP@
+AMTAR = @AMTAR@
+AUTOKEY = @AUTOKEY@
+AWK = @AWK@
+CC = @CC@
+CFLAGS = @CFLAGS@
+CHUTEST = @CHUTEST@
+CLKTEST = @CLKTEST@
+CPP = @CPP@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+DCFD = @DCFD@
+DEPDIR = @DEPDIR@
+LDFLAGS = @LDFLAGS@
+LIBPARSE = @LIBPARSE@
+LIBRSAREF = @LIBRSAREF@
+LN_S = @LN_S@
+MAKEINFO = @MAKEINFO@
+MAKE_ADJTIMED = @MAKE_ADJTIMED@
+MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
+MAKE_LIBPARSE = @MAKE_LIBPARSE@
+MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
+MAKE_LIBRSAREF = @MAKE_LIBRSAREF@
+MAKE_NTPTIME = @MAKE_NTPTIME@
+MAKE_NTP_GENKEYS = @MAKE_NTP_GENKEYS@
+MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
+MAKE_TICKADJ = @MAKE_TICKADJ@
+PACKAGE = @PACKAGE@
+PATH_PERL = @PATH_PERL@
+PATH_SH = @PATH_SH@
+PROPDELAY = @PROPDELAY@
+RANLIB = @RANLIB@
+RSAREF = @RSAREF@
+TESTDCF = @TESTDCF@
+U = @U@
+VERSION = @VERSION@
+install_sh = @install_sh@
+
+
+EXTRA_DIST = libefence.3 CHANGES
+libefence_a_SOURCES = efence.h efence.c page.c print.c
+check_PROGRAMS = eftest tstheap
+# TESTS = eftest tstheap
+noinst_LIBRARIES = libefence.a
+LDADD = libefence.a
+subdir = ElectricFence
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES = 
+LIBRARIES =  $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I..
+CPPFLAGS = @CPPFLAGS@
+LIBS = @LIBS@
+libefence_a_AR = $(AR) cru
+libefence_a_LIBADD = 
+am_libefence_a_OBJECTS =  efence.o page.o print.o
+libefence_a_OBJECTS =  $(am_libefence_a_OBJECTS)
+AR = ar
+eftest_SOURCES = eftest.c
+eftest_OBJECTS =  eftest.o
+eftest_LDADD = $(LDADD)
+eftest_DEPENDENCIES =  libefence.a
+eftest_LDFLAGS = 
+tstheap_SOURCES = tstheap.c
+tstheap_OBJECTS =  tstheap.o
+tstheap_LDADD = $(LDADD)
+tstheap_DEPENDENCIES =  libefence.a
+tstheap_LDFLAGS = 
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES =  $(libefence_a_SOURCES) eftest.c tstheap.c
+DIST_COMMON =  README COPYING Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+GZIP_ENV = --best
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+DEP_FILES =  @AMDEP@ $(DEPDIR)/efence.Po $(DEPDIR)/eftest.Po \
+$(DEPDIR)/page.Po $(DEPDIR)/print.Po $(DEPDIR)/tstheap.Po
+SOURCES = $(libefence_a_SOURCES) eftest.c tstheap.c
+OBJECTS = $(am_libefence_a_OBJECTS) eftest.o tstheap.o
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .c .h .o
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) 
+       cd $(top_srcdir) && $(AUTOMAKE) --gnu ElectricFence/Makefile
+
+Makefile: $(srcdir)/Makefile.in  $(top_builddir)/config.status $(BUILT_SOURCES)
+       cd $(top_builddir) \
+         && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+       -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+mostlyclean-compile:
+       -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+       -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+libefence.a: $(libefence_a_OBJECTS) $(libefence_a_DEPENDENCIES)
+       -rm -f libefence.a
+       $(libefence_a_AR) libefence.a $(libefence_a_OBJECTS) $(libefence_a_LIBADD)
+       $(RANLIB) libefence.a
+
+mostlyclean-checkPROGRAMS:
+
+clean-checkPROGRAMS:
+       -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS)
+
+distclean-checkPROGRAMS:
+
+maintainer-clean-checkPROGRAMS:
+
+eftest: $(eftest_OBJECTS) $(eftest_DEPENDENCIES)
+       @rm -f eftest
+       $(LINK) $(eftest_LDFLAGS) $(eftest_OBJECTS) $(eftest_LDADD) $(LIBS)
+
+tstheap: $(tstheap_OBJECTS) $(tstheap_DEPENDENCIES)
+       @rm -f tstheap
+       $(LINK) $(tstheap_LDFLAGS) $(tstheap_OBJECTS) $(tstheap_LDADD) $(LIBS)
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique $(LISP)
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+         || etags $(ETAGS_ARGS) $$tags  $$unique $(LISP)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+       -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+distdir: $(DISTFILES)
+       @for file in $(DISTFILES); do \
+         d=$(srcdir); \
+         if test -d $$d/$$file; then \
+           cp -pR $$d/$$file $(distdir); \
+         else \
+           test -f $(distdir)/$$file \
+           || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+           || cp -p $$d/$$file $(distdir)/$$file || :; \
+         fi; \
+       done
+
+@AMDEP@include $(DEPDIR)/efence.Po
+@AMDEP@include $(DEPDIR)/eftest.Po
+@AMDEP@include $(DEPDIR)/page.Po
+@AMDEP@include $(DEPDIR)/print.Po
+@AMDEP@include $(DEPDIR)/tstheap.Po
+
+mostlyclean-depend:
+
+clean-depend:
+
+distclean-depend:
+       -rm -rf $(DEPDIR)
+
+maintainer-clean-depend:
+
+@AMDEP@CCDEPMODE = @CCDEPMODE@
+
+.c.o:
+@AMDEP@        source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP@        depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP@        $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+       $(COMPILE) -c -o $@ `test -f $< || echo '$(srcdir)/'`$<
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+       $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+install-exec: install-exec-am
+
+install-data-am:
+install-data: install-data-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES)
+all-redirect: all-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f Makefile $(CONFIG_CLEAN_FILES)
+       -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+       -rm -f Makefile.in
+mostlyclean-am:  mostlyclean-noinstLIBRARIES mostlyclean-compile \
+               mostlyclean-checkPROGRAMS mostlyclean-tags \
+               mostlyclean-depend mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am:  clean-noinstLIBRARIES clean-compile clean-checkPROGRAMS \
+               clean-tags clean-depend clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am:  distclean-noinstLIBRARIES distclean-compile \
+               distclean-checkPROGRAMS distclean-tags distclean-depend \
+               distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am:  maintainer-clean-noinstLIBRARIES \
+               maintainer-clean-compile maintainer-clean-checkPROGRAMS \
+               maintainer-clean-tags maintainer-clean-depend \
+               maintainer-clean-generic distclean-am
+       @echo "This command is intended for maintainers to use;"
+       @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-checkPROGRAMS \
+distclean-checkPROGRAMS clean-checkPROGRAMS \
+maintainer-clean-checkPROGRAMS tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir mostlyclean-depend \
+distclean-depend clean-depend maintainer-clean-depend info-am info \
+dvi-am dvi check-local check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-am install-data install-am \
+install uninstall-am uninstall all-redirect all-am all install-strip \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+# Un-comment the following if you are running HP/UX.
+# CFLAGS= -Aa -g -D_HPUX_SOURCE -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+# Un-comment the following if you are running AIX. This makes sure you won't
+# get the shared-library malloc() rather than the Electric Fence malloc().
+# COMPILE THE PROGRAMS YOU ARE DEBUGGING WITH THESE FLAGS, TOO.
+# CFLAGS= -g -bnso -bnodelcsect -bI:/lib/syscalls.exp
+
+# Un-comment the following if you are running SunOS 4.X
+# Note the definition of PAGE_PROTECTION_VIOLATED_SIGNAL. This may vary
+# depend on what version of Sun hardware you have.
+# You'll probably have to link the program you are debugging with -Bstatic
+# as well if using Sun's compiler, -static if using GCC.
+# CFLAGS= -g -Bstatic -DPAGE_PROTECTION_VIOLATED_SIGNAL=SIGBUS
+
+check-local:
+       ./eftest
+       ./tstheap 3072
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/ElectricFence/README b/ElectricFence/README
new file mode 100644 (file)
index 0000000..8223850
--- /dev/null
@@ -0,0 +1,46 @@
+This is Electric Fence 2.0.5
+
+Electric Fence is a different kind of malloc() debugger. It uses the virtual
+memory hardware of your system to detect when software overruns the boundaries
+of a malloc() buffer. It will also detect any accesses of memory that has
+been released by free(). Because it uses the VM hardware for detection,
+Electric Fence stops your program on the first instruction that causes
+a bounds violation. It's then trivial to use a debugger to display the
+offending statement.
+
+This version will run on:
+       Linux kernel version 1.1.83 and above. Earlier kernels have problems
+       with the memory protection implementation.
+
+       All System V Revision 4 platforms (and possibly earlier revisions)
+       including:
+               Every 386 System V I've heard of.
+               Solaris 2.x
+               SGI IRIX 5.0 (but not 4.x)
+
+       IBM AIX on the RS/6000.
+
+       SunOS 4.X (using an ANSI C compiler and probably static linking).
+
+       HP/UX 9.01, and possibly earlier versions.
+
+       OSF 1.3 (and possibly earlier versions) on a DECalpha.
+
+On some of these platforms, you'll have to uncomment lines in the Makefile
+that apply to your particular system.
+
+If you test Electric Fence on a platform not mentioned here, please send me a
+report.
+
+It will probably port to any ANSI/POSIX system that provides mmap(), and
+mprotect(), as long as mprotect() has the capability to turn off all access
+to a memory page, and mmap() can use /dev/zero or the MAP_ANONYMOUS flag
+to create virtual memory pages.
+
+Complete information on the use of Electric Fence is in the manual page
+libefence.3 .
+
+       Thanks
+
+       Bruce Perens
+       Bruce@Pixar.com
diff --git a/ElectricFence/efence.c b/ElectricFence/efence.c
new file mode 100644 (file)
index 0000000..f797e75
--- /dev/null
@@ -0,0 +1,786 @@
+/*
+ * Electric Fence - Red-Zone memory allocator.
+ * Bruce Perens, 1988, 1993
+ * 
+ * This is a special version of malloc() and company for debugging software
+ * that is suspected of overrunning or underrunning the boundaries of a
+ * malloc buffer, or touching free memory.
+ *
+ * It arranges for each malloc buffer to be followed (or preceded)
+ * in the address space by an inaccessable virtual memory page,
+ * and for free memory to be inaccessable. If software touches the
+ * inaccessable page, it will get an immediate segmentation
+ * fault. It is then trivial to uncover the offending code using a debugger.
+ *
+ * An advantage of this product over most malloc debuggers is that this one
+ * detects reading out of bounds as well as writing, and this one stops on
+ * the exact instruction that causes the error, rather than waiting until the
+ * next boundary check.
+ *
+ * There is one product that debugs malloc buffer overruns
+ * better than Electric Fence: "Purify" from Purify Systems, and that's only
+ * a small part of what Purify does. I'm not affiliated with Purify, I just
+ * respect a job well done.
+ *
+ * This version of malloc() should not be linked into production software,
+ * since it tremendously increases the time and memory overhead of malloc().
+ * Each malloc buffer will consume a minimum of two virtual memory pages,
+ * this is 16 kilobytes on many systems. On some systems it will be necessary
+ * to increase the amount of swap space in order to debug large programs that
+ * perform lots of allocation, because of the per-buffer overhead.
+ */
+#include "efence.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <string.h>
+
+#ifdef malloc
+#undef malloc
+#endif
+
+#ifdef calloc
+#undef calloc
+#endif
+
+static const char      version[] = "\n  Electric Fence 2.0.5"
+ " Copyright (C) 1987-1995 Bruce Perens.\n";
+
+/*
+ * MEMORY_CREATION_SIZE is the amount of memory to get from the operating
+ * system at one time. We'll break that memory down into smaller pieces for
+ * malloc buffers. One megabyte is probably a good value.
+ */
+#define                        MEMORY_CREATION_SIZE    1024 * 1024
+
+/*
+ * Enum Mode indicates the status of a malloc buffer.
+ */
+enum _Mode {
+       NOT_IN_USE = 0, /* Available to represent a malloc buffer. */
+       FREE,           /* A free buffer. */
+       ALLOCATED,      /* A buffer that is in use. */
+       PROTECTED,      /* A freed buffer that can not be allocated again. */
+       INTERNAL_USE    /* A buffer used internally by malloc(). */
+};
+typedef enum _Mode     Mode;
+
+/*
+ * Struct Slot contains all of the information about a malloc buffer except
+ * for the contents of its memory.
+ */
+struct _Slot {
+       void *          userAddress;
+       void *          internalAddress;
+       size_t          userSize;
+       size_t          internalSize;
+       Mode            mode;
+};
+typedef struct _Slot   Slot;
+
+/*
+ * EF_ALIGNMENT is a global variable used to control the default alignment
+ * of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
+ * so that its name matches the name of the environment variable that is used
+ * to set it. This gives the programmer one less name to remember.
+ * If the value is -1, it will be set from the environment or sizeof(int)
+ * at run time.
+ */
+int            EF_ALIGNMENT = -1;
+
+/*
+ * EF_PROTECT_FREE is a global variable used to control the disposition of
+ * memory that is released using free(). It is all-caps so that its name
+ * matches the name of the environment variable that is used to set it.
+ * If its value is greater non-zero, memory released by free is made
+ * inaccessable and never allocated again. Any software that touches free
+ * memory will then get a segmentation fault. If its value is zero, freed
+ * memory will be available for reallocation, but will still be inaccessable
+ * until it is reallocated.
+ * If the value is -1, it will be set from the environment or to 0 at run-time.
+ */
+int            EF_PROTECT_FREE = -1;
+
+/*
+ * EF_PROTECT_BELOW is used to modify the behavior of the allocator. When
+ * its value is non-zero, the allocator will place an inaccessable page
+ * immediately _before_ the malloc buffer in the address space, instead
+ * of _after_ it. Use this to detect malloc buffer under-runs, rather than
+ * over-runs. It won't detect both at the same time, so you should test your
+ * software twice, once with this value clear, and once with it set.
+ * If the value is -1, it will be set from the environment or to zero at
+ * run-time
+ */
+int            EF_PROTECT_BELOW = -1;
+
+/*
+ * EF_ALLOW_MALLOC_0 is set if Electric Fence is to allow malloc(0). I
+ * trap malloc(0) by default because it is a common source of bugs.
+ */
+int            EF_ALLOW_MALLOC_0 = -1;
+
+/*
+ * allocationList points to the array of slot structures used to manage the
+ * malloc arena.
+ */
+static Slot *          allocationList = 0;
+
+/*
+ * allocationListSize is the size of the allocation list. This will always
+ * be a multiple of the page size.
+ */
+static size_t          allocationListSize = 0;
+
+/*
+ * slotCount is the number of Slot structures in allocationList.
+ */
+static size_t          slotCount = 0;
+
+/*
+ * unUsedSlots is the number of Slot structures that are currently available
+ * to represent new malloc buffers. When this number gets too low, we will
+ * create new slots.
+ */
+static size_t          unUsedSlots = 0;
+
+/*
+ * slotsPerPage is the number of slot structures that fit in a virtual
+ * memory page.
+ */
+static size_t          slotsPerPage = 0;
+
+/*
+ * internalUse is set when allocating and freeing the allocatior-internal
+ * data structures.
+ */
+static int             internalUse = 0;
+
+/*
+ * noAllocationListProtection is set to tell malloc() and free() not to
+ * manipulate the protection of the allocation list. This is only set in
+ * realloc(), which does it to save on slow system calls, and in
+ * allocateMoreSlots(), which does it because it changes the allocation list.
+ */
+static int             noAllocationListProtection = 0;
+
+/*
+ * bytesPerPage is set at run-time to the number of bytes per virtual-memory
+ * page, as returned by Page_Size().
+ */
+static size_t          bytesPerPage = 0;
+
+/*
+ * internalError is called for those "shouldn't happen" errors in the
+ * allocator.
+ */
+static void
+internalError(void)
+{
+       EF_Abort("Internal error in allocator.");
+}
+
+/*
+ * initialize sets up the memory allocation arena and the run-time
+ * configuration information.
+ */
+static void
+initialize(void)
+{
+       size_t  size = MEMORY_CREATION_SIZE;
+       size_t  slack;
+       char *  string;
+       Slot *  slot;
+
+       EF_Print(version);
+
+       /*
+        * Import the user's environment specification of the default
+        * alignment for malloc(). We want that alignment to be under
+        * user control, since smaller alignment lets us catch more bugs,
+        * however some software will break if malloc() returns a buffer
+        * that is not word-aligned.
+        *
+        * I would like
+        * alignment to be zero so that we could catch all one-byte
+        * overruns, however if malloc() is asked to allocate an odd-size
+        * buffer and returns an address that is not word-aligned, or whose
+        * size is not a multiple of the word size, software breaks.
+        * This was the case with the Sun string-handling routines,
+        * which can do word fetches up to three bytes beyond the end of a
+        * string. I handle this problem in part by providing
+        * byte-reference-only versions of the string library functions, but
+        * there are other functions that break, too. Some in X Windows, one
+        * in Sam Leffler's TIFF library, and doubtless many others.
+        */
+       if ( EF_ALIGNMENT == -1 ) {
+               if ( (string = getenv("EF_ALIGNMENT")) != 0 )
+                       EF_ALIGNMENT = (size_t)atoi(string);
+               else
+                       EF_ALIGNMENT = sizeof(int);
+       }
+
+       /*
+        * See if the user wants to protect the address space below a buffer,
+        * rather than that above a buffer.
+        */
+       if ( EF_PROTECT_BELOW == -1 ) {
+               if ( (string = getenv("EF_PROTECT_BELOW")) != 0 )
+                       EF_PROTECT_BELOW = (atoi(string) != 0);
+               else
+                       EF_PROTECT_BELOW = 0;
+       }
+
+       /*
+        * See if the user wants to protect memory that has been freed until
+        * the program exits, rather than until it is re-allocated.
+        */
+       if ( EF_PROTECT_FREE == -1 ) {
+               if ( (string = getenv("EF_PROTECT_FREE")) != 0 )
+                       EF_PROTECT_FREE = (atoi(string) != 0);
+               else
+                       EF_PROTECT_FREE = 0;
+       }
+
+       /*
+        * See if the user wants to allow malloc(0).
+        */
+       if ( EF_ALLOW_MALLOC_0 == -1 ) {
+               if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )
+                       EF_ALLOW_MALLOC_0 = (atoi(string) != 0);
+               else
+                       EF_ALLOW_MALLOC_0 = 0;
+       }
+
+       /*
+        * Get the run-time configuration of the virtual memory page size.
+        */
+       bytesPerPage = Page_Size();
+
+       /*
+        * Figure out how many Slot structures to allocate at one time.
+        */
+       slotCount = slotsPerPage = bytesPerPage / sizeof(Slot);
+       allocationListSize = bytesPerPage;
+
+       if ( allocationListSize > size )
+               size = allocationListSize;
+
+       if ( (slack = size % bytesPerPage) != 0 )
+               size += bytesPerPage - slack;
+
+       /*
+        * Allocate memory, and break it up into two malloc buffers. The
+        * first buffer will be used for Slot structures, the second will
+        * be marked free.
+        */
+       slot = allocationList = (Slot *)Page_Create(size);
+       memset((char *)allocationList, 0, allocationListSize);
+
+       slot[0].internalSize = slot[0].userSize = allocationListSize;
+       slot[0].internalAddress = slot[0].userAddress = allocationList;
+       slot[0].mode = INTERNAL_USE;
+       if ( size > allocationListSize ) {
+               slot[1].internalAddress = slot[1].userAddress
+                = ((char *)slot[0].internalAddress) + slot[0].internalSize;
+               slot[1].internalSize
+                = slot[1].userSize = size - slot[0].internalSize;
+               slot[1].mode = FREE;
+       }
+
+       /*
+        * Deny access to the free page, so that we will detect any software
+        * that treads upon free memory.
+        */
+       Page_DenyAccess(slot[1].internalAddress, slot[1].internalSize);
+
+       /*
+        * Account for the two slot structures that we've used.
+        */
+       unUsedSlots = slotCount - 2;
+}
+
+/*
+ * allocateMoreSlots is called when there are only enough slot structures
+ * left to support the allocation of a single malloc buffer.
+ */
+static void
+allocateMoreSlots(void)
+{
+       size_t  newSize = allocationListSize + bytesPerPage;
+       void *  newAllocation;
+       void *  oldAllocation = allocationList;
+
+       Page_AllowAccess(allocationList, allocationListSize);
+       noAllocationListProtection = 1;
+       internalUse = 1;
+
+       newAllocation = malloc(newSize);
+       memcpy(newAllocation, allocationList, allocationListSize);
+       memset(&(((char *)newAllocation)[allocationListSize]), 0, bytesPerPage);
+
+       allocationList = (Slot *)newAllocation;
+       allocationListSize = newSize;
+       slotCount += slotsPerPage;
+       unUsedSlots += slotsPerPage;
+
+       free(oldAllocation);
+
+       /*
+        * Keep access to the allocation list open at this point, because
+        * I am returning to memalign(), which needs that access.
+        */
+       noAllocationListProtection = 0;
+       internalUse = 0;
+}
+
+/*
+ * This is the memory allocator. When asked to allocate a buffer, allocate
+ * it in such a way that the end of the buffer is followed by an inaccessable
+ * memory page. If software overruns that buffer, it will touch the bad page
+ * and get an immediate segmentation fault. It's then easy to zero in on the
+ * offending code with a debugger.
+ *
+ * There are a few complications. If the user asks for an odd-sized buffer,
+ * we would have to have that buffer start on an odd address if the byte after
+ * the end of the buffer was to be on the inaccessable page. Unfortunately,
+ * there is lots of software that asks for odd-sized buffers and then
+ * requires that the returned address be word-aligned, or the size of the
+ * buffer be a multiple of the word size. An example are the string-processing
+ * functions on Sun systems, which do word references to the string memory
+ * and may refer to memory up to three bytes beyond the end of the string.
+ * For this reason, I take the alignment requests to memalign() and valloc()
+ * seriously, and 
+ * 
+ * Electric Fence wastes lots of memory. I do a best-fit allocator here
+ * so that it won't waste even more. It's slow, but thrashing because your
+ * working set is too big for a system's RAM is even slower. 
+ */
+extern C_LINKAGE void *
+memalign(size_t alignment, size_t userSize)
+{
+       register Slot * slot;
+       register size_t count;
+       Slot *          fullSlot = 0;
+       Slot *          emptySlots[2];
+       size_t          internalSize;
+       size_t          slack;
+       char *          address;
+
+       if ( allocationList == 0 )
+               initialize();
+
+       if ( userSize == 0 && !EF_ALLOW_MALLOC_0 )
+               EF_Abort("Allocating 0 bytes, probably a bug.");
+
+       /*
+        * If EF_PROTECT_BELOW is set, all addresses returned by malloc()
+        * and company will be page-aligned.
+        */
+       if ( !EF_PROTECT_BELOW && alignment > 1 ) {
+               if ( (slack = userSize % alignment) != 0 )
+                       userSize += alignment - slack;
+       }
+
+       /*
+        * The internal size of the buffer is rounded up to the next page-size
+        * boudary, and then we add another page's worth of memory for the
+        * dead page.
+        */
+       internalSize = userSize + bytesPerPage;
+       if ( (slack = internalSize % bytesPerPage) != 0 )
+               internalSize += bytesPerPage - slack;
+
+       /*
+        * These will hold the addresses of two empty Slot structures, that
+        * can be used to hold information for any memory I create, and any
+        * memory that I mark free.
+        */
+       emptySlots[0] = 0;
+       emptySlots[1] = 0;
+
+       /*
+        * The internal memory used by the allocator is currently
+        * inaccessable, so that errant programs won't scrawl on the
+        * allocator's arena. I'll un-protect it here so that I can make
+        * a new allocation. I'll re-protect it before I return.
+        */
+       if ( !noAllocationListProtection )
+               Page_AllowAccess(allocationList, allocationListSize);
+
+       /*
+        * If I'm running out of empty slots, create some more before
+        * I don't have enough slots left to make an allocation.
+        */
+       if ( !internalUse && unUsedSlots < 7 ) {
+               allocateMoreSlots();
+       }
+       
+       /*
+        * Iterate through all of the slot structures. Attempt to find a slot
+        * containing free memory of the exact right size. Accept a slot with
+        * more memory than we want, if the exact right size is not available.
+        * Find two slot structures that are not in use. We will need one if
+        * we split a buffer into free and allocated parts, and the second if
+        * we have to create new memory and mark it as free.
+        *
+        */
+       
+       for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
+               if ( slot->mode == FREE
+                && slot->internalSize >= internalSize ) {
+                       if ( !fullSlot
+                        ||slot->internalSize < fullSlot->internalSize){
+                               fullSlot = slot;
+                               if ( slot->internalSize == internalSize
+                                && emptySlots[0] )
+                                       break;  /* All done, */
+                       }
+               }
+               else if ( slot->mode == NOT_IN_USE ) {
+                       if ( !emptySlots[0] )
+                               emptySlots[0] = slot;
+                       else if ( !emptySlots[1] )
+                               emptySlots[1] = slot;
+                       else if ( fullSlot
+                        && fullSlot->internalSize == internalSize )
+                               break;  /* All done. */
+               }
+               slot++;
+       }
+       if ( !emptySlots[0] )
+               internalError();
+
+       if ( !fullSlot ) {
+               /*
+                * I get here if I haven't been able to find a free buffer
+                * with all of the memory I need. I'll have to create more
+                * memory. I'll mark it all as free, and then split it into
+                * free and allocated portions later.
+                */
+               size_t  chunkSize = MEMORY_CREATION_SIZE;
+
+               if ( !emptySlots[1] )
+                       internalError();
+
+               if ( chunkSize < internalSize )
+                       chunkSize = internalSize;
+
+               if ( (slack = chunkSize % bytesPerPage) != 0 )
+                       chunkSize += bytesPerPage - slack;
+
+               /* Use up one of the empty slots to make the full slot. */
+               fullSlot = emptySlots[0];
+               emptySlots[0] = emptySlots[1];
+               fullSlot->internalAddress = Page_Create(chunkSize);
+               fullSlot->internalSize = chunkSize;
+               fullSlot->mode = FREE;
+               unUsedSlots--;
+       }
+
+       /*
+        * If I'm allocating memory for the allocator's own data structures,
+        * mark it INTERNAL_USE so that no errant software will be able to
+        * free it.
+        */
+       if ( internalUse )
+               fullSlot->mode = INTERNAL_USE;
+       else
+               fullSlot->mode = ALLOCATED;
+
+       /*
+        * If the buffer I've found is larger than I need, split it into
+        * an allocated buffer with the exact amount of memory I need, and
+        * a free buffer containing the surplus memory.
+        */
+       if ( fullSlot->internalSize > internalSize ) {
+               emptySlots[0]->internalSize
+                = fullSlot->internalSize - internalSize;
+               emptySlots[0]->internalAddress
+                = ((char *)fullSlot->internalAddress) + internalSize;
+               emptySlots[0]->mode = FREE;
+               fullSlot->internalSize = internalSize;
+               unUsedSlots--;
+       }
+
+       if ( !EF_PROTECT_BELOW ) {
+               /*
+                * Arrange the buffer so that it is followed by an inaccessable
+                * memory page. A buffer overrun that touches that page will
+                * cause a segmentation fault.
+                */
+               address = (char *)fullSlot->internalAddress;
+
+               /* Set up the "live" page. */
+               if ( internalSize - bytesPerPage > 0 )
+                               Page_AllowAccess(
+                                fullSlot->internalAddress
+                               ,internalSize - bytesPerPage);
+                       
+               address += internalSize - bytesPerPage;
+
+               /* Set up the "dead" page. */
+               if ( EF_PROTECT_FREE )
+                       Page_Delete(address, bytesPerPage);
+               else
+                       Page_DenyAccess(address, bytesPerPage);
+
+               /* Figure out what address to give the user. */
+               address -= userSize;
+       }
+       else {  /* EF_PROTECT_BELOW != 0 */
+               /*
+                * Arrange the buffer so that it is preceded by an inaccessable
+                * memory page. A buffer underrun that touches that page will
+                * cause a segmentation fault.
+                */
+               address = (char *)fullSlot->internalAddress;
+
+               /* Set up the "dead" page. */
+               if ( EF_PROTECT_FREE )
+                       Page_Delete(address, bytesPerPage);
+               else
+                       Page_DenyAccess(address, bytesPerPage);
+                       
+               address += bytesPerPage;
+
+               /* Set up the "live" page. */
+               if ( internalSize - bytesPerPage > 0 )
+                       Page_AllowAccess(address, internalSize - bytesPerPage);
+       }
+
+       fullSlot->userAddress = address;
+       fullSlot->userSize = userSize;
+
+       /*
+        * Make the pool's internal memory inaccessable, so that the program
+        * being debugged can't stomp on it.
+        */
+       if ( !internalUse )
+               Page_DenyAccess(allocationList, allocationListSize);
+
+       return address;
+}
+
+/*
+ * Find the slot structure for a user address.
+ */
+static Slot *
+slotForUserAddress(void * address)
+{
+       register Slot * slot = allocationList;
+       register size_t count = slotCount;
+       
+       for ( ; count > 0; count-- ) {
+               if ( slot->userAddress == address )
+                       return slot;
+               slot++;
+       }
+
+       return 0;
+}
+
+/*
+ * Find the slot structure for an internal address.
+ */
+static Slot *
+slotForInternalAddress(void * address)
+{
+       register Slot * slot = allocationList;
+       register size_t count = slotCount;
+       
+       for ( ; count > 0; count-- ) {
+               if ( slot->internalAddress == address )
+                       return slot;
+               slot++;
+       }
+       return 0;
+}
+
+/*
+ * Given the internal address of a buffer, find the buffer immediately
+ * before that buffer in the address space. This is used by free() to
+ * coalesce two free buffers into one.
+ */
+static Slot *
+slotForInternalAddressPreviousTo(void * address)
+{
+       register Slot * slot = allocationList;
+       register size_t count = slotCount;
+       
+       for ( ; count > 0; count-- ) {
+               if ( ((char *)slot->internalAddress)
+                + slot->internalSize == address )
+                       return slot;
+               slot++;
+       }
+       return 0;
+}
+
+extern C_LINKAGE void
+free(void * address)
+{
+       Slot *  slot;
+       Slot *  previousSlot = 0;
+       Slot *  nextSlot = 0;
+
+       if ( address == 0 )
+               return;
+
+       if ( allocationList == 0 )
+               EF_Abort("free() called before first malloc().");
+
+       if ( !noAllocationListProtection )
+               Page_AllowAccess(allocationList, allocationListSize);
+
+       slot = slotForUserAddress(address);
+
+       if ( !slot )
+               EF_Abort("free(%a): address not from malloc().", address);
+
+       if ( slot->mode != ALLOCATED ) {
+               if ( internalUse && slot->mode == INTERNAL_USE )
+                       /* Do nothing. */;
+               else {
+                       EF_Abort(
+                        "free(%a): freeing free memory."
+                       ,address);
+               }
+       }
+
+       if ( EF_PROTECT_FREE )
+               slot->mode = PROTECTED;
+       else
+               slot->mode = FREE;
+
+       previousSlot = slotForInternalAddressPreviousTo(slot->internalAddress);
+       nextSlot = slotForInternalAddress(
+        ((char *)slot->internalAddress) + slot->internalSize);
+
+       if ( previousSlot
+        && (previousSlot->mode == FREE || previousSlot->mode == PROTECTED) ) {
+               /* Coalesce previous slot with this one. */
+               previousSlot->internalSize += slot->internalSize;
+               if ( EF_PROTECT_FREE )
+                       previousSlot->mode = PROTECTED;
+
+               slot->internalAddress = slot->userAddress = 0;
+               slot->internalSize = slot->userSize = 0;
+               slot->mode = NOT_IN_USE;
+               slot = previousSlot;
+               unUsedSlots++;
+       }
+       if ( nextSlot
+        && (nextSlot->mode == FREE || nextSlot->mode == PROTECTED) ) {
+               /* Coalesce next slot with this one. */
+               slot->internalSize += nextSlot->internalSize;
+               nextSlot->internalAddress = nextSlot->userAddress = 0;
+               nextSlot->internalSize = nextSlot->userSize = 0;
+               nextSlot->mode = NOT_IN_USE;
+               unUsedSlots++;
+       }
+
+       slot->userAddress = slot->internalAddress;
+       slot->userSize = slot->internalSize;
+
+       /*
+        * Free memory is _always_ set to deny access. When EF_PROTECT_FREE
+        * is true, free memory is never reallocated, so it remains access
+        * denied for the life of the process. When EF_PROTECT_FREE is false, 
+        * the memory may be re-allocated, at which time access to it will be
+        * allowed again.
+        *
+        * Some operating systems allow munmap() with single-page resolution,
+        * and allow you to un-map portions of a region, rather than the
+        * entire region that was mapped with mmap(). On those operating
+        * systems, we can release protected free pages with Page_Delete(),
+        * in the hope that the swap space attached to those pages will be
+        * released as well.
+        */
+       if ( EF_PROTECT_FREE )
+           Page_Delete(slot->internalAddress, slot->internalSize);
+       else
+           Page_DenyAccess(slot->internalAddress, slot->internalSize);
+
+       if ( !noAllocationListProtection )
+               Page_DenyAccess(allocationList, allocationListSize);
+}
+
+extern C_LINKAGE void *
+realloc(void * oldBuffer, size_t newSize)
+{
+       void *  newBuffer = malloc(newSize);
+
+       if ( oldBuffer ) {
+               size_t  size;
+               Slot *  slot;
+
+               Page_AllowAccess(allocationList, allocationListSize);
+               noAllocationListProtection = 1;
+               
+               slot = slotForUserAddress(oldBuffer);
+
+               if ( slot == 0 )
+                       EF_Abort(
+                        "realloc(%a, %d): address not from malloc()."
+                       ,oldBuffer
+                       ,newSize);
+
+               if ( newSize < (size = slot->userSize) )
+                       size = newSize;
+
+               if ( size > 0 )
+                       memcpy(newBuffer, oldBuffer, size);
+
+               free(oldBuffer);
+               noAllocationListProtection = 0;
+               Page_DenyAccess(allocationList, allocationListSize);
+
+               if ( size < newSize )
+                       memset(&(((char *)newBuffer)[size]), 0, newSize - size);
+               
+               /* Internal memory was re-protected in free() */
+       }
+
+       return newBuffer;
+}
+
+extern C_LINKAGE void *
+malloc(size_t size)
+{
+       if ( allocationList == 0 )
+               initialize();   /* This sets EF_ALIGNMENT */
+
+       return memalign(EF_ALIGNMENT, size);
+}
+
+extern C_LINKAGE void *
+calloc(size_t nelem, size_t elsize)
+{
+       size_t  size = nelem * elsize;
+       void *  allocation = malloc(size);
+
+       memset(allocation, 0, size);
+       return allocation;
+}
+
+/*
+ * This will catch more bugs if you remove the page alignment, but it
+ * will break some software.
+ */
+extern C_LINKAGE void *
+valloc (size_t size)
+{
+       return memalign(bytesPerPage, size);
+}
+
+#ifdef __hpux
+/*
+ * HP-UX 8/9.01 strcat reads a word past source when doing unaligned copies!
+ * Work around it here. The bug report has been filed with HP.
+ */
+char *strcat(char *d, const char *s)
+{
+       strcpy(d+strlen(d), s);
+       return d;
+}
+#endif
diff --git a/ElectricFence/efence.h b/ElectricFence/efence.h
new file mode 100644 (file)
index 0000000..60eb30f
--- /dev/null
@@ -0,0 +1,42 @@
+#include <sys/types.h>
+#include <sys/param.h>
+
+/*
+ * ef_number is the largest unsigned integer we'll need. On systems that
+ * support 64-bit pointers, this may be "unsigned long long".
+ */
+#if defined(USE_LONG_LONG)
+typedef unsigned long long     ef_number;
+#else
+typedef unsigned long          ef_number;
+#endif
+
+/*
+ * NBBY is the number of bits per byte. Some systems define it in
+ * <sys/param.h> .
+ */
+#ifndef        NBBY
+#define        NBBY    8
+#endif
+
+/*
+ * This is used to declare functions with "C" linkage if we are compiling
+ * with C++ .
+ */
+#ifdef __cplusplus
+#define        C_LINKAGE       "C"
+#else
+#define        C_LINKAGE
+#endif
+
+void                   Page_AllowAccess(void * address, size_t size);
+void *                 Page_Create(size_t size);
+void                   Page_Delete(void * address, size_t size);
+void                   Page_DenyAccess(void * address, size_t size);
+size_t                 Page_Size(void);
+
+void                   EF_Abort(const char * message, ...);
+void                   EF_Exit(const char * message, ...);
+void                   EF_Print(const char * message, ...);
+void                   EF_Lock();
+void                   EF_UnLock();
diff --git a/ElectricFence/eftest.c b/ElectricFence/eftest.c
new file mode 100644 (file)
index 0000000..03489d0
--- /dev/null
@@ -0,0 +1,219 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include "efence.h"
+
+/*
+ * Electric Fence confidence tests.
+ * Make sure all of the various functions of Electric Fence work correctly.
+ */
+
+#ifndef        PAGE_PROTECTION_VIOLATED_SIGNAL
+#define        PAGE_PROTECTION_VIOLATED_SIGNAL SIGSEGV
+#endif
+
+struct diagnostic {
+       int             (*test)(void);
+       int             expectedStatus;
+       const char *    explanation;
+};
+
+extern int     EF_PROTECT_BELOW;
+extern int     EF_ALIGNMENT;
+
+static jmp_buf env;
+
+/*
+ * There is still too little standardization of the arguments and return
+ * type of signal handler functions.
+ */
+static
+void
+segmentationFaultHandler(
+int signalNumber
+#if ( defined(_AIX) )
+, ...
+#endif
+)
+ {
+       signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
+       longjmp(env, 1);
+}
+
+static int
+gotSegmentationFault(int (*test)(void))
+{
+       if ( setjmp(env) == 0 ) {
+               int                     status;
+
+               signal(PAGE_PROTECTION_VIOLATED_SIGNAL
+               ,segmentationFaultHandler);
+               status = (*test)();
+               signal(PAGE_PROTECTION_VIOLATED_SIGNAL, SIG_DFL);
+               return status;
+       }
+       else
+               return 1;
+}
+
+static char *  allocation;
+/* c is global so that assignments to it won't be optimized out. */
+char   c;
+
+static int
+testSizes(void)
+{
+       /*
+        * If ef_number can't hold all of the bits of a void *, have the user
+        * add -DUSE_ LONG_LONG to the compiler flags so that ef_number will be
+        * declared as "unsigned long long" instead of "unsigned long".
+        */
+       return ( sizeof(ef_number) < sizeof(void *) );
+}
+
+static int
+allocateMemory(void)
+{
+       allocation = (char *)malloc(1);
+
+       if ( allocation != 0 )
+               return 0;
+       else
+               return 1;
+}
+
+static int
+freeMemory(void)
+{
+       free(allocation);
+       return 0;
+}
+
+static int
+protectBelow(void)
+{
+       EF_PROTECT_BELOW = 1;
+       return 0;
+}
+
+static int
+read0(void)
+{
+       c = *allocation;
+
+       return 0;
+}
+
+static int
+write0(void)
+{
+       *allocation = 1;
+
+       return 0;
+}
+
+static int
+read1(void)
+{
+       c = allocation[1];
+
+       return 0;
+}
+
+static int
+readMinus1(void)
+{
+       c = allocation[-1];
+       return 0;
+}
+
+static struct diagnostic diagnostics[] = {
+       {
+               testSizes, 0,
+               "Please add -DLONG_LONG to the compiler flags and recompile."
+       },
+       {
+               allocateMemory, 0,
+               "Allocation 1: This test allocates a single byte of memory."
+       },
+       {
+               read0, 0,
+               "Read valid memory 1: This test reads the allocated memory."
+       },
+       {
+               write0, 0,
+               "Write valid memory 1: This test writes the allocated memory."
+       },
+       {
+               read1, 1,
+               "Read overrun: This test reads beyond the end of the buffer."
+       },
+       {
+               freeMemory, 0,
+               "Free memory: This test frees the allocated memory."
+       },
+       {
+               protectBelow, 0,
+               "Protect below: This sets Electric Fence to protect\n"
+               "the lower boundary of a malloc buffer, rather than the\n"
+               "upper boundary."
+       },
+       {
+               allocateMemory, 0,
+               "Allocation 2: This allocates memory with the lower boundary"
+               " protected."
+       },
+       {
+               read0, 0,
+               "Read valid memory 2: This test reads the allocated memory."
+       },
+       {
+               write0, 0,
+               "Write valid memory 2: This test writes the allocated memory."
+       },
+       {
+               readMinus1, 1,
+               "Read underrun: This test reads before the beginning of the"
+               " buffer."
+       },
+       {
+               0, 0, 0
+       }
+};
+
+static const char      failedTest[]
+ = "Electric Fence confidence test failed.\n";
+
+static const char      newline = '\n';
+
+int
+main(int argc, char * * argv)
+{
+       static const struct diagnostic *        diag = diagnostics;
+       
+
+       EF_PROTECT_BELOW = 0;
+       EF_ALIGNMENT = 0;
+
+       while ( diag->explanation != 0 ) {
+               int     status = gotSegmentationFault(diag->test);
+
+               if ( status != diag->expectedStatus ) {
+                       /*
+                        * Don't use stdio to print here, because stdio
+                        * uses malloc() and we've just proven that malloc()
+                        * is broken. Also, use _exit() instead of exit(),
+                        * because _exit() doesn't flush stdio.
+                        */
+                       write(2, failedTest, sizeof(failedTest) - 1);
+                       write(2, diag->explanation, strlen(diag->explanation));
+                       write(2, &newline, 1);
+                       _exit(-1);
+               }
+               diag++;
+       }
+       return 0;
+}
diff --git a/ElectricFence/libefence.3 b/ElectricFence/libefence.3
new file mode 100644 (file)
index 0000000..34fd25c
--- /dev/null
@@ -0,0 +1,382 @@
+.TH efence 3 27-April-1993
+.SH NAME
+efence \- Electric Fence Malloc Debugger
+.SH SYNOPSIS
+.nf
+.ft B
+#include <stdlib.h>
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * malloc (size_t size);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void free (void *ptr);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * realloc (void *ptr, size_t size);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * calloc (size_t nelem, size_t elsize);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * memalign (size_t alignment, size_t size);
+.ft
+.fi
+.LP
+.nf
+.ft B
+void * valloc (size_t size);
+.ft
+.fi
+.LP
+.nf
+.ft B
+extern int EF_ALIGNMENT;
+.ft
+.fi
+.LP
+.nf
+.ft B
+extern int EF_PROTECT_BELOW;
+.ft
+.fi
+.LP
+.nf
+.ft B
+extern int EF_PROTECT_FREE;
+.ft
+.fi
+.SH DESCRIPTION
+.I Electric Fence
+helps you detect two common programming bugs:
+software that overruns the boundaries of a malloc() memory
+allocation, and software that touches a memory allocation that has been
+released by free(). Unlike other malloc() debuggers, Electric Fence will
+detect
+.I read
+accesses as well as writes, and it will pinpoint the exact instruction that
+causes an error. It has been in use at Pixar since 1987, and at many other
+sites for years.
+.LP
+Electric Fence uses the virtual memory hardware of your computer to place an
+inaccessible memory page immediately after (or before, at the user's option)
+each memory allocation. When software reads or writes this inaccessible page,
+the
+hardware issues a segmentation fault, stopping the program at the offending
+instruction. It is then trivial to find the erroneous statement using your
+favorite debugger. In a similar manner, memory that has been released by
+free() is made inaccessible, and any code that touches it will get a
+segmentation fault.
+.LP
+Simply linking your application with libefence.a will allow you to detect
+most, but not all, malloc buffer overruns and accesses of free memory.
+If you want to be reasonably sure that you've found
+.I all
+bugs of this type, you'll have to read and understand the rest of this
+man page.
+.SH USAGE
+Link your program with the library
+.B libefence.a .
+Make sure you are
+.I not
+linking with
+.B -lmalloc,
+.B -lmallocdebug,
+or with other malloc-debugger or malloc-enhancer libraries.
+You can only use one at a time.
+If your system administrator
+has installed Electric Fence for public use, you'll be able to use the
+.B -lefence
+argument to the linker, otherwise you'll have to put the path-name for
+.B libefence.a
+in the linker's command line.
+Some systems will require special arguments to the linker to assure that
+you are using the Electric Fence malloc() and not the one from your C library.
+On AIX systems, you may have to use the flags
+.br
+.B -bnso
+.B -bnodelcsect
+.B -bI:/lib/syscalls.exp
+.br
+On Sun systems running SunOS 4.X, you'll probably have to use
+.B -Bstatic.
+.LP
+Run your program
+.I using a debugger. 
+It's easier to work this way than to create a
+.B core
+file and post-mortem debug it. Electric Fence can create
+.I huge
+core files, and some operating systems will thus take minutes simply to dump
+core! Some operating systems will not create usable core files from programs
+that are linked with Electric Fence.
+If your program has one of the errors detected by Electric Fence, it will
+get a segmentation fault (SIGSEGV) at the offending instruction. Use the
+debugger to locate the erroneous statement, and repair it.
+.SH GLOBAL AND ENVIRONMENT VARIABLES
+Electric Fence has four configuration switches that can be enabled via
+the shell environment, or by setting the value of global integer variables
+using a debugger. These switches change what bugs Electric Fence will detect,
+so it's important that you know how to use them.
+.TP
+EF_ALIGNMENT
+This is an integer that specifies the alignment for any memory allocations
+that will be returned by malloc(), calloc(), and realloc().
+The value is specified in
+bytes, thus a value of 4 will cause memory to be aligned to 32-bit boundaries
+unless your system doesn't have a 8-bit characters. EF_ALIGNMENT is set to
+sizeof(int) by default, since that is generally the word-size of your CPU.
+If your program requires that allocations be aligned to 64-bit
+boundaries and you have a 32-bit
+.B int
+you'll have to set this value to 8. This is the case when compiling with the
+.B -mips2
+flag on MIPS-based systems such as those from SGI.
+The memory allocation that is returned by Electric Fence malloc() is aligned
+using the value in EF_ALIGNMENT, and
+.I its size the multiple of
+.I that value
+that is greater than or equal to the requested size.
+For this reason, you will sometimes want to set EF_ALIGNMENT to 0 (no
+alignment), so that
+you can detect overruns of less than your CPU's word size. Be sure to read
+the section
+.I WORD-ALIGNMENT AND OVERRUN DETECTION
+in this manual page before you try this.
+To change this value, set EF_ALIGNMENT in the shell environment to an
+integer value, or assign
+to the global integer variable EF_ALIGNMENT using a debugger.
+.TP
+EF_PROTECT_BELOW
+Electric Fence usually places an inaccessible page immediately after each
+memory allocation, so that software that runs past the end of the allocation
+will be detected. Setting EF_PROTECT_BELOW to 1 causes Electric Fence
+to place the inaccessible page
+.I before
+the allocation in the address space, so that under-runs will be detected
+instead of over-runs.
+When EF_PROTECT_BELOW is set, the EF_ALIGNMENT parameter is ignored.
+All allocations will be aligned to virtual-memory-page boundaries, and
+their size will be the exact size that was requested.
+To change this value, set EF_PROTECT_BELOW in the shell environment to an
+integer value, or assign to the global integer variable EF_PROTECT_BELOW using
+a debugger.
+.TP
+EF_PROTECT_FREE
+Electric Fence usually returns free memory to a pool from which it may be
+re-allocated. If you suspect that a program may be touching free memory,
+set EF_PROTECT_FREE to 1. This will cause Electric Fence to never re-allocate
+memory once it has been freed, so that any access to free memory will be
+detected. Some programs will use tremendous amounts of memory when this
+parameter is set.
+To change this value, set EF_PROTECT_FREE in the shell environment to an
+integer value, or assign to the global integer variable EF_PROTECT_FREE using
+a debugger.
+.TP
+EF_ALLOW_MALLOC_0
+By default, Electric Fence traps calls to malloc() with a size of zero, because
+they are often the result of a software bug. If EF_ALLOW_MALLOC_0 is non-zero,
+the software will not trap calls to malloc() with a size of zero.
+To change this value, set EF_ALLOC_MALLOC_0 in the shell environment to an
+integer value, or assign to the global integer variable EF_ALLOC_MALLOC_0 using
+a debugger.
+.SH WORD-ALIGNMENT AND OVERRUN DETECTION
+There is a conflict between the alignment restrictions that malloc() operates
+under and the debugging strategy used by Electric Fence. When detecting
+overruns, Electric Fence malloc() allocates two or more virtual memory
+pages for each allocation. The last page is made inaccessible in such a way
+that any read, write, or execute access will cause a segmentation fault.
+Then, Electric Fence malloc() will return an address such that the first
+byte after
+the end of the allocation is on the inaccessible page.
+Thus, any overrun
+of the allocation will cause a segmentation fault.
+.LP
+It follows that the
+address returned by malloc() is the address of the inaccessible page minus
+the size of the memory allocation.
+Unfortunately, malloc() is required to return
+.I word-aligned
+allocations, since many CPUs can only access a word when its address is aligned.
+The conflict happens when software makes a memory allocation using a size that
+is not a multiple of the word size, and expects to do word accesses to that
+allocation. The location of the inaccessible page is fixed by hardware at
+a word-aligned address. If Electric Fence malloc() is to return an aligned
+address, it must increase the size of the allocation to a multiple of the
+word size.
+In addition, the functions memalign() and valloc() must honor explicit
+specifications on the alignment of the memory allocation, and this, as well
+can only be implemented by increasing the size of the allocation.
+Thus, there will be situations in which the end of a memory allocation
+contains some padding space, and accesses of that padding space will not
+be detected, even if they are overruns.
+.LP
+Electric Fence provides the variable EF_ALIGNMENT so that the user can
+control the default alignment used by malloc(), calloc(), and realloc().
+To debug overruns as small as a single byte, you can set EF_ALIGNMENT to
+zero. This will result in Electric Fence malloc() returning unaligned
+addresses for allocations with sizes that are not a multiple of the word
+size. This is not a problem in most cases, because compilers must pad the
+size of objects so that alignment restrictions are honored when storing
+those objects in arrays. The problem surfaces when software allocates
+odd-sized buffers for objects that must be word-aligned. One case of this
+is software that allocates a buffer to contain a structure and a
+string, and the string has an odd size (this example was in a popular TIFF
+library). If word references are made to un-aligned buffers, you will see
+a bus error (SIGBUS) instead of a segmentation fault. The only way to fix
+this is to re-write the offending code to make byte references or not make
+odd-sized allocations, or to set EF_ALIGNMENT to the word size.
+.LP
+Another example of software incompatible with
+EF_ALIGNMENT < word-size
+is the strcmp() function and other string functions on SunOS (and probably
+Solaris), which make word-sized accesses to character strings, and may
+attempt to access up to three bytes beyond the end of a string. These
+result in a segmentation fault (SIGSEGV). The only way around this is to
+use versions of the string functions that perform byte references instead
+of word references.
+.SH INSTRUCTIONS FOR DEBUGGING YOUR PROGRAM
+.TP
+1.
+Link with libefence.a as explained above.
+.TP
+2.
+Run your program in a debugger and fix any overruns or accesses to free memory.
+.TP
+3.
+Quit the debugger.
+.TP
+4.
+Set EF_PROTECT_BELOW = 1 in the shell environment.
+.TP
+5.
+Repeat step 2, this time repairing underruns if they occur.
+.TP
+6.
+Quit the debugger.
+.TP
+7.
+Read the restrictions in the section on
+.I WORD-ALIGNMENT AND OVERRUN DETECTION.
+See if you can
+set EF_ALIGNMENT to 0 and repeat step 2. Sometimes this will be too much work,
+or there will be problems with library routines for which you don't have the
+source, that will prevent you from doing this.
+.SH MEMORY USAGE AND EXECUTION SPEED
+Since Electric Fence uses at least two virtual memory pages for each of its
+allocations, it's a terrible memory hog. I've sometimes found it necessary to
+add a swap file using swapon(8) so that the system would have enough virtual
+memory to debug my program. Also, the way we manipulate memory results in
+various cache and translation buffer entries being flushed with each call
+to malloc or free. The end result is that your program will be much slower
+and use more resources while you are debugging it with Electric Fence.
+.LP
+Don't leave libefence.a linked into production software! Use it only
+for debugging.
+.SH PORTING
+Electric Fence is written for ANSI C. You should be able to port it with
+simple changes to the Makefile and to page.c,
+which contains the memory management primitives .
+Many POSIX platforms will require only a re-compile.
+The operating system facilities required to port Electric Fence are:
+.IP
+A way to allocate memory pages
+.br
+A way to make selected pages inaccessible.
+.br
+A way to make the pages accessible again.
+.br
+A way to detect when a program touches an inaccessible page.
+.br
+A way to print messages.
+.LP
+Please e-mail me a copy of any changes you have to make, so that I can
+merge them into the distribution.
+.SH AUTHOR
+Bruce Perens
+.SH WARNINGS
+I have tried to do as good a job as I can on this software, but I doubt
+that it is even theoretically possible to make it bug-free.
+This software has no warranty. It will not detect some bugs that you might
+expect it to detect, and will indicate that some non-bugs are bugs.
+Bruce Perens and/or Pixar will not be liable to any claims resulting
+from the use of this software or the ideas within it.
+The entire responsibility for its use must
+be assumed by the user. If you use it and it results in loss of life
+and/or property, tough. If it leads you on a wild goose chase and you waste
+two weeks debugging something, too bad.
+If you can't deal with the above, please don't use the software! I've written
+this in an attempt to help other people, not to get myself sued or prosecuted.
+.SH LICENSE
+Copyright 1987-1995 Bruce Perens. All rights reserved.
+.br
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License, Version 2,
+as published by the Free Software Foundation. A copy of this license is
+distributed with this software in the file "COPYING".
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Read the
+file "COPYING" for more details.
+.SH CONTACTING THE AUTHOR
+.nf
+Bruce Perens
+c/o Pixar
+1001 West Cutting Blvd., Suite 200
+Richmond, CA 94804
+
+Telephone: 510-215-3502
+Fax: 510-236-0388
+Internet: Bruce@Pixar.com
+.fi
+.ft
+.SH FILES
+/dev/zero: Source of memory pages (via mmap(2)).
+.SH SEE ALSO
+malloc(3), mmap(2), mprotect(2), swapon(8)
+.SH DIAGNOSTICS
+Segmentation Fault: Examine the offending statement for violation of the
+boundaries of a memory allocation.
+.br
+Bus Error: See the section on
+.I WORD-ALIGNMENT AND OVERRUN DETECTION.
+in this manual page.
+.SH BUGS
+My explanation of the alignment issue could be improved.
+.LP
+Some Sun systems running SunOS 4.1 are reported to signal an access to a
+protected page with
+.B  SIGBUS
+rather than
+.B SIGSEGV,
+I suspect this is an undocumented feature of a particular Sun hardware
+version, not just the operating system.
+On these systems, eftest will fail with a bus error until you modify the
+Makefile to define
+.B PAGE_PROTECTION_VIOLATED_SIGNAL
+as
+.B SIGBUS.
+.LP
+There are, without doubt, other bugs and porting issues. Please contact me via
+e-mail if you have any bug reports, ideas, etc.
+.SH WHAT'S BETTER
+PURIFY, from Purify Systems, does a much better job than Electric Fence, and
+does much more. It's available at this writing on SPARC and HP.
+I'm not affiliated with Purify, I just think it's a wonderful product
+and you should check it out.
diff --git a/ElectricFence/page.c b/ElectricFence/page.c
new file mode 100644 (file)
index 0000000..1351887
--- /dev/null
@@ -0,0 +1,186 @@
+#include "efence.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+/*
+ * Lots of systems are missing the definition of PROT_NONE.
+ */
+#ifndef        PROT_NONE
+#define        PROT_NONE       0
+#endif
+
+/*
+ * 386 BSD has MAP_ANON instead of MAP_ANONYMOUS.
+ */
+#if ( !defined(MAP_ANONYMOUS) && defined(MAP_ANON) )
+#define        MAP_ANONYMOUS   MAP_ANON
+#endif
+
+/*
+ * For some reason, I can't find mprotect() in any of the headers on
+ * IRIX or SunOS 4.1.2
+ */
+/* extern C_LINKAGE int mprotect(void * addr, size_t len, int prot); */
+
+static caddr_t startAddr = (caddr_t) 0;
+
+#if ( !defined(sgi) && !defined(_AIX) )
+extern int     sys_nerr;
+extern char *  sys_errlist[];
+#endif
+
+static const char *
+stringErrorReport(void)
+{
+#if ( defined(sgi) )
+       return strerror(oserror());
+#elif ( defined(_AIX) )
+       return strerror(errno);
+#else
+       if ( errno > 0 && errno < sys_nerr )
+               return sys_errlist[errno];
+       else
+               return "Unknown error.\n";
+#endif
+}
+
+/*
+ * Create memory.
+ */
+#if defined(MAP_ANONYMOUS)
+void *
+Page_Create(size_t size)
+{
+       caddr_t         allocation;
+
+       /*
+        * In this version, "startAddr" is a _hint_, not a demand.
+        * When the memory I map here is contiguous with other
+        * mappings, the allocator can coalesce the memory from two
+        * or more mappings into one large contiguous chunk, and thus
+        * might be able to find a fit that would not otherwise have
+        * been possible. I could _force_ it to be contiguous by using
+        * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
+        * generated by other software, etc.
+        */
+       allocation = (caddr_t) mmap(
+        startAddr
+       ,(int)size
+       ,PROT_READ|PROT_WRITE
+       ,MAP_PRIVATE|MAP_ANONYMOUS
+       ,-1
+       ,0);
+
+#ifndef        __hpux
+       /*
+        * Set the "address hint" for the next mmap() so that it will abut
+        * the mapping we just created.
+        *
+        * HP/UX 9.01 has a kernel bug that makes mmap() fail sometimes
+        * when given a non-zero address hint, so we'll leave the hint set
+        * to zero on that system. HP recently told me this is now fixed.
+        * Someone please tell me when it is probable to assume that most
+        * of those systems that were running 9.01 have been upgraded.
+        */
+       startAddr = allocation + size;
+#endif
+
+       if ( allocation == (caddr_t)-1 )
+               EF_Exit("mmap() failed: %s", stringErrorReport());
+
+       return (void *)allocation;
+}
+#else
+void *
+Page_Create(size_t size)
+{
+       static int      devZeroFd = -1;
+       caddr_t         allocation;
+
+       if ( devZeroFd == -1 ) {
+               devZeroFd = open("/dev/zero", O_RDWR);
+               if ( devZeroFd < 0 )
+                       EF_Exit(
+                        "open() on /dev/zero failed: %s"
+                       ,stringErrorReport());
+       }
+
+       /*
+        * In this version, "startAddr" is a _hint_, not a demand.
+        * When the memory I map here is contiguous with other
+        * mappings, the allocator can coalesce the memory from two
+        * or more mappings into one large contiguous chunk, and thus
+        * might be able to find a fit that would not otherwise have
+        * been possible. I could _force_ it to be contiguous by using
+        * the MMAP_FIXED flag, but I don't want to stomp on memory mappings
+        * generated by other software, etc.
+        */
+       allocation = (caddr_t) mmap(
+        startAddr
+       ,(int)size
+       ,PROT_READ|PROT_WRITE
+       ,MAP_PRIVATE
+       ,devZeroFd
+       ,0);
+
+       startAddr = allocation + size;
+
+       if ( allocation == (caddr_t)-1 )
+               EF_Exit("mmap() failed: %s", stringErrorReport());
+
+       return (void *)allocation;
+}
+#endif
+
+static void
+mprotectFailed(void)
+{
+       EF_Exit("mprotect() failed: %s", stringErrorReport());
+}
+
+void
+Page_AllowAccess(void * address, size_t size)
+{
+       if ( mprotect((caddr_t)address, size, PROT_READ|PROT_WRITE) < 0 )
+               mprotectFailed();
+}
+
+void
+Page_DenyAccess(void * address, size_t size)
+{
+       if ( mprotect((caddr_t)address, size, PROT_NONE) < 0 )
+               mprotectFailed();
+}
+
+void
+Page_Delete(void * address, size_t size)
+{
+       if ( munmap((caddr_t)address, size) < 0 )
+               Page_DenyAccess(address, size);
+}
+
+#if defined(_SC_PAGESIZE)
+size_t
+Page_Size(void)
+{
+       return (size_t)sysconf(_SC_PAGESIZE);
+}
+#elif defined(_SC_PAGE_SIZE)
+size_t
+Page_Size(void)
+{
+       return (size_t)sysconf(_SC_PAGE_SIZE);
+}
+#else
+/* extern int  getpagesize(); */
+size_t
+Page_Size(void)
+{
+       return getpagesize();
+}
+#endif
diff --git a/ElectricFence/print.c b/ElectricFence/print.c
new file mode 100644 (file)
index 0000000..f32ed2b
--- /dev/null
@@ -0,0 +1,170 @@
+#include "efence.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+
+/*
+ * These routines do their printing without using stdio. Stdio can't
+ * be used because it calls malloc(). Internal routines of a malloc()
+ * debugger should not re-enter malloc(), so stdio is out.
+ */
+
+/*
+ * NUMBER_BUFFER_SIZE is the longest character string that could be needed
+ * to represent an unsigned integer, assuming we might print in base 2.
+ */
+#define        NUMBER_BUFFER_SIZE      (sizeof(ef_number) * NBBY)
+
+static void
+printNumber(ef_number number, ef_number base)
+{
+       char            buffer[NUMBER_BUFFER_SIZE];
+       char *          s = &buffer[NUMBER_BUFFER_SIZE];
+       int             size;
+       
+       do {
+               ef_number       digit;
+
+               if ( --s == buffer )
+                       EF_Abort("Internal error printing number.");
+
+               digit = number % base;
+
+               if ( digit < 10 )
+                       *s = '0' + digit;
+               else
+                       *s = 'a' + digit - 10;
+
+       } while ( (number /= base) > 0 );
+
+       size = &buffer[NUMBER_BUFFER_SIZE] - s;
+
+       if ( size > 0 )
+               write(2, s, size);
+}
+
+static void
+vprint(const char * pattern, va_list args)
+{
+       static const char       bad_pattern[] =
+        "\nBad pattern specifier %%%c in EF_Print().\n";
+       const char *    s = pattern;
+       char            c;
+
+       while ( (c = *s++) != '\0' ) {
+               if ( c == '%' ) {
+                       c = *s++;
+                       switch ( c ) {
+                       case '%':
+                               (void) write(2, &c, 1);
+                               break;
+                       case 'a':
+                               /*
+                                * Print an address passed as a void pointer.
+                                * The type of ef_number must be set so that
+                                * it is large enough to contain all of the
+                                * bits of a void pointer.
+                                */
+                               printNumber(
+                                (ef_number)va_arg(args, void *)
+                               ,0x10);
+                               break;
+                       case 's':
+                               {
+                                       const char *    string;
+                                       size_t          length;
+
+                                       string = va_arg(args, char *);
+                                       length = strlen(string);
+
+                                       (void) write(2, string, length);
+                               }
+                               break;
+                       case 'd':
+                               {
+                                       int     n = va_arg(args, int);
+
+                                       if ( n < 0 ) {
+                                               char    c = '-';
+                                               write(2, &c, 1);
+                                               n = -n;
+                                       }
+                                       printNumber(n, 10);
+                               }
+                               break;
+                       case 'x':
+                               printNumber(va_arg(args, u_int), 0x10);
+                               break;
+                       case 'c':
+                               {
+                                       char    c = va_arg(args, char);
+                                       
+                                       (void) write(2, &c, 1);
+                               }
+                               break;
+                       default:
+                               {
+                                       EF_Print(bad_pattern, c);
+                               }
+               
+                       }
+               }
+               else
+                       (void) write(2, &c, 1);
+       }
+}
+
+void
+EF_Abort(const char * pattern, ...)
+{
+       va_list args;
+
+       va_start(args, pattern);
+
+       EF_Print("\nElectricFence Aborting: ");
+       vprint(pattern, args);
+       EF_Print("\n");
+
+       va_end(args);
+
+       /*
+        * I use kill(getpid(), SIGILL) instead of abort() because some
+        * mis-guided implementations of abort() flush stdio, which can
+        * cause malloc() or free() to be called.
+        */
+       kill(getpid(), SIGILL);
+       /* Just in case something handles SIGILL and returns, exit here. */
+       _exit(-1);
+}
+
+void
+EF_Exit(const char * pattern, ...)
+{
+       va_list args;
+
+       va_start(args, pattern);
+
+       EF_Print("\nElectricFence Exiting: ");
+       vprint(pattern, args);
+       EF_Print("\n");
+
+       va_end(args);
+
+       /*
+        * I use _exit() because the regular exit() flushes stdio,
+        * which may cause malloc() or free() to be called.
+        */
+       _exit(-1);
+}
+
+void
+EF_Print(const char * pattern, ...)
+{
+       va_list args;
+
+       va_start(args, pattern);
+       vprint(pattern, args);
+       va_end(args);
+}
diff --git a/ElectricFence/tstheap.c b/ElectricFence/tstheap.c
new file mode 100644 (file)
index 0000000..c712fed
--- /dev/null
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include "efence.h"
+
+/*
+ * This is a simple program to exercise the allocator. It allocates and frees
+ * memory in a pseudo-random fashion. It should run silently, using up time
+ * and resources on your system until you stop it or until it has gone
+ * through TEST_DURATION (or the argument) iterations of the loop.
+ */
+
+extern C_LINKAGE double drand48(void); /* For pre-ANSI C systems */
+
+#define        POOL_SIZE       1024
+#define        LARGEST_BUFFER  30000
+#define        TEST_DURATION   1000000
+
+void * pool[POOL_SIZE];
+
+#ifdef FAKE_DRAND48
+/*
+ * Add -DFAKE_DRAND48 to your compile flags if your system doesn't
+ * provide drand48().
+ */
+
+#ifndef        ULONG_MAX
+#define        ULONG_MAX       ~(1L)
+#endif
+
+double
+drand48(void)
+{
+       return (random() / (double)ULONG_MAX);
+}
+#endif
+
+int
+main(int argc, char * * argv)
+{
+       int     count = 0;
+       int     duration = TEST_DURATION;
+
+       if ( argc >= 2 )
+               duration = atoi(argv[1]);
+
+       for ( ; count < duration; count++ ) {
+               void * *        element = &pool[(int)(drand48() * POOL_SIZE)];
+               size_t          size = (size_t)(drand48() * (LARGEST_BUFFER + 1));
+
+               if ( *element ) {
+                       free( *element );
+                       *element = 0;
+               }
+               else if ( size > 0 ) {
+                       *element = malloc(size);
+               }
+       }
+       return 0;
+}
index 580a9ca7afb520bdf6d28911dadd2e5ecd02e310..807b7935cc2ebe0bc590bb7c7a680a4bdc33d2b4 100755 (executable)
--- a/configure
+++ b/configure
@@ -11126,13 +11126,13 @@ cat >$CONFIG_STATUS <<EOF
 
 # Files that config.status was made for.
 config_files="\\
-  Makefile adjtimed/Makefile clockstuff/Makefile include/Makefile
-  kernel/Makefile kernel/sys/Makefile libntp/Makefile libparse/Makefile
-  librsaref/Makefile ntpd/Makefile ntpdc/Makefile ntpdate/Makefile
-  ntpq/Makefile ntptrace/Makefile parseutil/Makefile scripts/Makefile
-  scripts/calc_tickadj scripts/checktime scripts/freq_adj scripts/mkver
-  scripts/ntp-wait scripts/ntpsweep scripts/ntpver scripts/plot_summary
-  scripts/summary util/Makefile"
+  Makefile adjtimed/Makefile clockstuff/Makefile ElectricFence/Makefile
+  include/Makefile kernel/Makefile kernel/sys/Makefile libntp/Makefile
+  libparse/Makefile librsaref/Makefile ntpd/Makefile ntpdc/Makefile
+  ntpdate/Makefile ntpq/Makefile ntptrace/Makefile parseutil/Makefile
+  scripts/Makefile scripts/calc_tickadj scripts/checktime scripts/freq_adj
+  scripts/mkver scripts/ntp-wait scripts/ntpsweep scripts/ntpver
+  scripts/plot_summary scripts/summary util/Makefile"
 config_headers="\\
   config.h"
 config_commands="\\
@@ -11218,6 +11218,7 @@ do
   'Makefile' ) CONFIG_FILES="\$CONFIG_FILES Makefile" ;;
   'adjtimed/Makefile' ) CONFIG_FILES="\$CONFIG_FILES adjtimed/Makefile" ;;
   'clockstuff/Makefile' ) CONFIG_FILES="\$CONFIG_FILES clockstuff/Makefile" ;;
+  'ElectricFence/Makefile' ) CONFIG_FILES="\$CONFIG_FILES ElectricFence/Makefile" ;;
   'include/Makefile' ) CONFIG_FILES="\$CONFIG_FILES include/Makefile" ;;
   'kernel/Makefile' ) CONFIG_FILES="\$CONFIG_FILES kernel/Makefile" ;;
   'kernel/sys/Makefile' ) CONFIG_FILES="\$CONFIG_FILES kernel/sys/Makefile" ;;
index 3bd929afb2a19ba842ea4093fd91de4bc28fc5c6..3be766cd0413e56f3f03a8cdb74a9eaef250e38f 100644 (file)
@@ -2985,6 +2985,7 @@ esac
 LIBOBJS=`echo $LIBOBJS|sed 's/\.o /\$U.o /g;s/\.o$/\$U.o/'`
 
 AC_CONFIG_FILES(Makefile adjtimed/Makefile clockstuff/Makefile \
+ElectricFence/Makefile
 include/Makefile kernel/Makefile kernel/sys/Makefile libntp/Makefile \
 libparse/Makefile librsaref/Makefile ntpd/Makefile ntpdc/Makefile \
 ntpdate/Makefile ntpq/Makefile ntptrace/Makefile parseutil/Makefile \