Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/e7d8f550c4c6b36edeb7d05ea065979b9f9fd468
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/e7d8f550c4c6b36edeb7d05ea065979b9f9fd468
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/e7d8f550c4c6b36edeb7d05ea065979b9f9fd468

The branch, chris/fortify has been created
        at  e7d8f550c4c6b36edeb7d05ea065979b9f9fd468 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=e7d8f550c4c6b36edeb7d05ea065979b9f9fd468
commit e7d8f550c4c6b36edeb7d05ea065979b9f9fd468
Author: Chris Young <[email protected]>
Commit: Chris Young <[email protected]>

    Attempt to fortify more files to catch alloc/free split between core and 
frontend

diff --git a/content/fetch.c b/content/fetch.c
index c5928ba..5c8769b 100644
--- a/content/fetch.c
+++ b/content/fetch.c
@@ -587,7 +587,7 @@ void fetch_free(struct fetch *f)
 {
        FETCH_LOG("Freeing fetch %p, fetcher %p", f, f->fetcher_handle);
 
-       fetchers[f->fetcherd].ops.free(f->fetcher_handle);
+       fetchers[f->fetcherd].ops.ffree(f->fetcher_handle);
 
        fetch_unref_fetcher(f->fetcherd);
 
diff --git a/content/fetchers.h b/content/fetchers.h
index 92b11dc..e58d873 100644
--- a/content/fetchers.h
+++ b/content/fetchers.h
@@ -83,7 +83,7 @@ struct fetcher_operation_table {
        /**
         * free a fetch allocated through the setup method.
         */
-       void (*free)(void *fetch);
+       void (*ffree)(void *fetch);
 
        /**
         * poll a fetcher to let it make progress.
diff --git a/content/fetchers/about.c b/content/fetchers/about.c
index 4d14020..76985a7 100644
--- a/content/fetchers/about.c
+++ b/content/fetchers/about.c
@@ -853,7 +853,7 @@ nserror fetch_about_register(void)
                .setup = fetch_about_setup,
                .start = fetch_about_start,
                .abort = fetch_about_abort,
-               .free = fetch_about_free,
+               .ffree = fetch_about_free,
                .poll = fetch_about_poll,
                .finalise = fetch_about_finalise
        };
diff --git a/content/fetchers/curl.c b/content/fetchers/curl.c
index 9ac390c..d242bed 100644
--- a/content/fetchers/curl.c
+++ b/content/fetchers/curl.c
@@ -1282,7 +1282,7 @@ nserror fetch_curl_register(void)
                .setup = fetch_curl_setup,
                .start = fetch_curl_start,
                .abort = fetch_curl_abort,
-               .free = fetch_curl_free,
+               .ffree = fetch_curl_free,
                .poll = fetch_curl_poll,
                .finalise = fetch_curl_finalise
        };
diff --git a/content/fetchers/data.c b/content/fetchers/data.c
index 84d0aa3..7302f9d 100644
--- a/content/fetchers/data.c
+++ b/content/fetchers/data.c
@@ -327,7 +327,7 @@ nserror fetch_data_register(void)
                .setup = fetch_data_setup,
                .start = fetch_data_start,
                .abort = fetch_data_abort,
-               .free = fetch_data_free,
+               .ffree = fetch_data_free,
                .poll = fetch_data_poll,
                .finalise = fetch_data_finalise
        };
diff --git a/content/fetchers/file.c b/content/fetchers/file.c
index 04184d2..8c145df 100644
--- a/content/fetchers/file.c
+++ b/content/fetchers/file.c
@@ -822,7 +822,7 @@ nserror fetch_file_register(void)
                .setup = fetch_file_setup,
                .start = fetch_file_start,
                .abort = fetch_file_abort,
-               .free = fetch_file_free,
+               .ffree = fetch_file_free,
                .poll = fetch_file_poll,
                .finalise = fetch_file_finalise
        };
diff --git a/content/fetchers/resource.c b/content/fetchers/resource.c
index 21ad8c7..8626942 100644
--- a/content/fetchers/resource.c
+++ b/content/fetchers/resource.c
@@ -461,7 +461,7 @@ nserror fetch_resource_register(void)
                .setup = fetch_resource_setup,
                .start = fetch_resource_start,
                .abort = fetch_resource_abort,
-               .free = fetch_resource_free,
+               .ffree = fetch_resource_free,
                .poll = fetch_resource_poll,
                .finalise = fetch_resource_finalise
        };
diff --git a/content/handlers/javascript/fetcher.c 
b/content/handlers/javascript/fetcher.c
index 839df26..80a53d8 100644
--- a/content/handlers/javascript/fetcher.c
+++ b/content/handlers/javascript/fetcher.c
@@ -208,7 +208,7 @@ nserror fetch_javascript_register(void)
                .setup = fetch_javascript_setup,
                .start = fetch_javascript_start,
                .abort = fetch_javascript_abort,
-               .free = fetch_javascript_free,
+               .ffree = fetch_javascript_free,
                .poll = fetch_javascript_poll,
                .finalise = fetch_javascript_finalise
        };
diff --git a/frontends/amiga/filetype.c b/frontends/amiga/filetype.c
index 05f130e..61e4929 100644
--- a/frontends/amiga/filetype.c
+++ b/frontends/amiga/filetype.c
@@ -352,7 +352,7 @@ static APTR ami_mime_guess_add_datatype(struct DataType 
*dt, lwc_string **lwc_mi
 {
        struct nsObject *node;
        char mimetype[100];
-       char *dt_name_lwr;
+       char *dt_name_lwr = NULL;
        struct ami_mime_entry *mimeentry;
        lwc_error lerror;
        struct DataTypeHeader *dth = dt->dtn_Header;
diff --git a/frontends/amiga/gui.c b/frontends/amiga/gui.c
index afb49a5..07c7214 100644
--- a/frontends/amiga/gui.c
+++ b/frontends/amiga/gui.c
@@ -334,7 +334,7 @@ bool ami_gui_map_filename(char **remapped, const char 
*path, const char *file, c
 static bool ami_gui_check_resource(char *fullpath, const char *file)
 {
        bool found = false;
-       char *remapped;
+       char *remapped = NULL;
        BPTR lock = 0;
        size_t fullpath_len = 1024;
 
diff --git a/frontends/amiga/options.h b/frontends/amiga/options.h
index 39e62dc..ef64425 100644
--- a/frontends/amiga/options.h
+++ b/frontends/amiga/options.h
@@ -20,7 +20,7 @@
 #define AMIGA_OPTIONS_H
 
 /* currently nothing here */
-
+#include "frontends/amiga/fortify/fortify.h"
 #endif
 
 
diff --git a/frontends/amiga/utf8.c b/frontends/amiga/utf8.c
index 24af8c8..1e34b00 100755
--- a/frontends/amiga/utf8.c
+++ b/frontends/amiga/utf8.c
@@ -16,6 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "amiga/os3support.h"
+
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
diff --git a/render/html_css_fetcher.c b/render/html_css_fetcher.c
index 05aef02..ac312a7 100644
--- a/render/html_css_fetcher.c
+++ b/render/html_css_fetcher.c
@@ -283,7 +283,7 @@ nserror html_css_fetcher_register(void)
                .setup = html_css_fetcher_setup,
                .start = html_css_fetcher_start,
                .abort = html_css_fetcher_abort,
-               .free = html_css_fetcher_free,
+               .ffree = html_css_fetcher_free,
                .poll = html_css_fetcher_poll,
                .finalise = html_css_fetcher_finalise
        };


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=bb9f91153bea94c2b54df9cb8476f4afa4911782
commit bb9f91153bea94c2b54df9cb8476f4afa4911782
Author: Chris Young <[email protected]>
Commit: Chris Young <[email protected]>

    Basic Fortify addition
    NB: Only built in to the frontend code, and won't catch AllocVec/FreeVec/etc

diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile
index e2769a0..bd5d092 100644
--- a/frontends/amiga/Makefile
+++ b/frontends/amiga/Makefile
@@ -38,6 +38,7 @@ else
 
   CFLAGS += -I$(GCCSDK_INSTALL_ENV)/include
   CFLAGS += $(shell $(PKG_CONFIG) --cflags tre)
+  CFLAGS += -DFORTIFY
 
   LDFLAGS += $(shell $(PKG_CONFIG) --static --libs libcurl openssl)
   LDFLAGS += $(shell $(PKG_CONFIG) --libs tre)
@@ -70,7 +71,7 @@ S_FRONTEND := gui.c tree.c history.c hotlist.c schedule.c 
file.c      \
        stringview/stringview.c stringview/urlhistory.c rtg.c           \
        agclass/amigaguide_class.c os3support.c font_diskfont.c         \
        selectmenu.c hash/xxhash.c font_cache.c font_bullet.c   \
-       fortify.c
+       fortify/fortify.c
 
 # This is the final source build list
 # Note this is deliberately *not* expanded here as common and image
diff --git a/frontends/amiga/os3support.h b/frontends/amiga/os3support.h
index 94d1d58..05d6aff 100644
--- a/frontends/amiga/os3support.h
+++ b/frontends/amiga/os3support.h
@@ -24,6 +24,8 @@
 #ifndef AMIGA_OS3SUPPORT_H_
 #define AMIGA_OS3SUPPORT_H_
 
+#include "amiga/fortify/fortify.h"
+
 #ifndef __amigaos4__
 
 #include <stdint.h>


commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=57085cea67962607b44c88408ed15da160ad863f
commit 57085cea67962607b44c88408ed15da160ad863f
Author: Chris Young <[email protected]>
Commit: Chris Young <[email protected]>

    Add Fortify 2.2 files to build
    --Testing only--

diff --git a/frontends/amiga/Makefile b/frontends/amiga/Makefile
index 2b727ca..e2769a0 100644
--- a/frontends/amiga/Makefile
+++ b/frontends/amiga/Makefile
@@ -69,7 +69,8 @@ S_FRONTEND := gui.c tree.c history.c hotlist.c schedule.c 
file.c      \
        datatypes.c dt_picture.c dt_anim.c dt_sound.c plugin_hack.c     \
        stringview/stringview.c stringview/urlhistory.c rtg.c           \
        agclass/amigaguide_class.c os3support.c font_diskfont.c         \
-       selectmenu.c hash/xxhash.c font_cache.c font_bullet.c
+       selectmenu.c hash/xxhash.c font_cache.c font_bullet.c   \
+       fortify.c
 
 # This is the final source build list
 # Note this is deliberately *not* expanded here as common and image
diff --git a/frontends/amiga/fortify/FORTIFY.DOC 
b/frontends/amiga/fortify/FORTIFY.DOC
new file mode 100755
index 0000000..b89fa06
--- /dev/null
+++ b/frontends/amiga/fortify/FORTIFY.DOC
@@ -0,0 +1,746 @@
+        Fortify - A fortified memory allocation shell for C and C++
+        -----------------------------------------------------------
+                        written by Simon P. Bullen
+
+                       Version 2.2, 1 November 1995
+
+
+
+            This  software  is  not public domain.  All material in
+        this  archive  is (C) Copyright 1995 Simon P.  Bullen.  The
+        software  is  freely distributable, with the condition that
+        no   more   than  a  nominal  fee  is  charged  for  media.
+        Everything  in  this distribution must be kept together, in
+        original, unmodified form.
+            The software may be modified for your own personal use,
+        but modified files may not be distributed.
+            The  material  is  provided "as is" without warranty of
+        any  kind.  The author accepts no responsibility for damage
+        caused by this software.
+            This  software  may not be used in any way by Microsoft
+        Corporation  or  its  subsidiaries, or current employees of
+        Microsoft Corporation or its subsidiaries.
+            This  software  may  not  be used for the construction,
+        development,  production,  or  testing of weapon systems of
+        any kind.
+            This  software  may  not  be used for the construction,
+        development,  production,  or  use  of plants/installations
+        which  include  the  processing  of radioactive/fissionable
+        material.
+
+
+
+    If  you  use  this  software  at  all,  I'd love to hear from you.  All
+questions, criticisms, suggestions, praise and postcards are most welcome.
+
+                     email:    [email protected]
+
+                     snail:    Simon P. Bullen
+                               PO BOX 12138
+                               A'Beckett St.
+                               Melbourne 3000
+                               Australia
+
+
+
+    CONTENTS
+    --------
+    Your archive should have the following files:
+
+    fortify.doc - This file. Read it first
+    fortify.cxx - Actual code. Rename to fortify.c for C only development
+    fortify.h   - Each file in your program should #include this
+    ufortify.h  - User configuration file. Here is where you set your options
+
+    test.c      - C tester
+    test2.cxx   - C++ tester
+    makefile    - Makefile for GCC to build the testers.
+
+
+
+    OVERVIEW
+    --------
+    Fortify  is  a  (fortified)  shell for memory allocations.  It supports
+malloc/calloc/realloc/strdup/free  and  new/delete.  It traps memory leaks,
+writes beyond and before memory blocks, writes to freed memory, free twice,
+freeing  memory  never  allocated,  and removes all randomness from reading
+uninitialized or free memory.
+  It  is a descendant of a library I wrote way back in 1990 called SafeMem.
+It can be adapted to most memory management functions; the original version
+of SafeMem worked only with the Amiga's AllocMem/FreeMem.
+    Fortify works by allocating extra space on each block.  This includes a
+private  header (which is used to keep track of Fortify's list of allocated
+memory),  and  two  "fortification zones" or "sentinels" (which are used to
+detect writing outside the bound of the user's memory).
+
+
+
+
+    PORTABILITY
+    -----------
+    Fortify is intended to be a highly portable tool.  It should work quite
+happily  in  any vaguely ANSI C/C++ environment, on any operating system or
+processor architecture without modification.
+    It  does  not,  however, support bizarre memory models.  A pointer is a
+pointer  is  a  pointer.  I have no intention of ever supporting any of the
+non-flat memory models used by some pretend operating systems.
+
+
+
+
+    Fortify INSTALLATION (C++)
+    --------------------------
+    To install Fortify, each source file will need to #include "fortify.h".
+To  enable  Fortify,  define  the symbol FORTIFY.  The makefile is the best
+place  to  do  this.   The symbol FORTIFY will need to be defined for every
+module, this includes "fortify.c" or "fortify.cxx".
+    If FORTIFY is not defined, it will compile away to nothing - it will be
+as  if  Fortify  was  never  installed  at  all  (you  should recompile all
+sourcecode with Fortify disabled for a release of your software).
+    If you do not have stdout available, you may wish to set an alternative
+output        function.         See       Fortify_SetOutputFunc()       and
+FORTIFY_AUTOMATIC_LOGFILE, below.
+    Your  program  will  need  to  link  in  "fortify.cxx" (after it's been
+compiled, of course).
+       You may also need to adjust some options in "ufortify.h" before Fortify
+will work correctly.  See "Compile Time Customizations", below.
+
+
+
+    Fortify INSTALLATION (C)
+    ------------------------
+    To  install  Fortify  into  a C program, simply rename "fortify.cxx" to
+"fortify.c",  and  follow  the  C++ instructions above.  "fortify.cxx" will
+compile  quite happily as C, as all the core Fortify code is C, and the C++
+specific code is surrounded by #ifdef __cplusplus/#endif.
+       You may also need to adjust some options in "ufortify.h" before Fortify
+will work correctly.  See "Compile Time Customizations", below.
+
+
+
+
+
+    COMPILE TIME CUSTOMIZATIONS
+    ---------------------------
+    The  file  "ufortify.h"  contains  many  #defines  that  you can use to
+customize  Fortify's  behavior.   Fortify  will  do  it's  best  to provide
+sensible  defaults  for  most of these options, if for some reason they are
+not present in "ufortify.h".
+  Most  of  the  options  are  merely user preferences that you may wish to
+change  or  turn  on  only when you are trying to track down a particularly
+nasty  bug.   There are a couple of configuration items, however, that will
+need  to be set correctly for Fortify to compile on your particular system.
+When  it  can,  Fortify  will  detect  a  compiler  and set the appropriate
+options.
+    Ideally,  Fortify would be able to be built under all compilers without
+modification, but due to differences in compilers and the devious nature of
+some  of  the stuff Fortify has to acheive, this is sadly not possible.  It
+is  my  aim  to  make  Fortify automatically configure itself for all major
+compilers   out   there,   so   if   you  need  to  adjust  some  of  these
+compiler-specific options to get Fortify to work under your system, I would
+greatly appreciate the code fragment that detects your compiler and sets up
+the correct options (these live in "fortify.h" - search for __GNUG__ for an
+example).
+
+
+
+    #define FORTIFY_PROVIDE_ARRAY_NEW
+    #define FORTIFY_PROVIDE_ARRAY_DELETE
+
+    Some  C++  compilers  have  separate  operators for newing and deleting
+arrays.   If  your  compiler does, you will need to define this symbol.  If
+you  are  unsure, turn them both on.  Your program won't compile or link if
+they  should  be off (providing your test code actually news and deletes an
+array).   GCC 2.6.3 and Borland C++ 4.5 both need these symbols.  Microsoft
+C++  1.5  and  SAS  6.5 C++ both don't.  Fortify will automatically turn on
+this option for GCC and Borland..
+    If both array new and array delete are enabled, Fortify will be able to
+ensure  that  you  always use the correct form of delete, and will issue an
+error message if you use the wrong one.
+
+    Fortify: Incorrect deallocator "delete[]" detected at test2.cxx.17
+             (0x7438ac2,1,test2.cxx.13) was allocated with "new"
+
+
+    #define FORTIFY_STRDUP
+
+    strdup()  is  a  non-ANSI function that is essentially a malloc() and a
+strcpy().    If   you   use   this   function,  you  will  need  to  enable
+FORTIFY_STRDUP,  so  that  the  memory  you  get back from strdup() will be
+allocated by Fortify. 
+       If  you  don't do this, Fortify will generate an error message when you
+attempt to free the memory.
+
+
+    #define FORTIFY_NO_PERCENT_P
+
+    Some  non-ANSI  versions  of sprintf() do not recognize "%p" as a valid
+conversion  specification.   Fortify  uses  "%p"  to  output  all  of  it's
+pointers.     If   your   sprintf()   does   not   support   "%p",   define
+FORTIFY_NO_PERCENT_P, and Fortify will use "%lx" instead.
+
+
+    #define FORTIFY_STORAGE
+
+    You  can  use  this to apply a storage type to all Fortify's exportable
+functions.   If  you  are putting Fortify in an export library for example,
+you may need to put __export here, for example.
+
+
+    #define FORTIFY_BEFORE_SIZE       32
+    #define FORTIFY_BEFORE_VALUE    0xA3
+    #define FORTIFY_AFTER_SIZE        32
+    #define FORTIFY_AFTER_VALUE     0xA5
+
+    These  values  define  how  much  "fortification" is placed around each
+memory  block  you  allocate.  Fortify will place FORTIFY_BEFORE_SIZE bytes
+worth  of  memory  right  before  your memory block, and FORTIFY_AFTER_SIZE
+bytes   after   your  memory  block,  and  these  will  be  initialized  to
+FORTIFY_BEFORE_VALUE and FORTIFY_AFTER_VALUE respectively.  If your program
+then  accidentally writes into either of these regions, Fortify will detect
+this, and issue an error message.
+    If  you don't want these fortifications to be allocated, specify a size
+of 0.  Note that the value parameters are 8 bits.
+
+    Fortify: Underwrite detected before block (0x743b462,123,test.c.14) at
+             test.c.16
+             Memory integrity was last verified at test.c.14
+       Address   Offset Data (a3)
+                        ...64 bytes skipped...
+     0x743b45a       64 a3a3a3a3 a3a3a341                      "�������A"
+
+
+    #define FORTIFY_ALIGNMENT            sizeof(double)
+
+    Many  processors  require  data objects to have a specific alignment in
+memory.   The  memory  allocators on these machines will only return memory
+blocks  aligned  correctly for the largest of these requirements.  Fortify,
+however,  adds  some  magic  cookies  to  the  start of it's memory blocks.
+Fortify  will guarantee that the amount of memory it adds to the front of a
+memory  block  will  be  a  multiple  of FORTIFY_ALIGNMENT (It does this by
+increasing  the  FORTIFY_BEFORE_SIZE, after taking into account the size of
+it's  private  header).   The default of sizeof(double) should work on most
+systems.
+
+
+    #define FORTIFY_FILL_ON_ALLOCATE
+    #define FORTIFY_FILL_ON_ALLOCATE_VALUE        0xA7
+
+    Programs  often  rely  on  uninitialized  memory  being  certain values
+(usually  0).   If you define FORTIFY_FILL_ON_ALLOCATE, all memory that you
+allocate  will  be initialized to FORTIFY_FILL_ON_ALLOCATE_VALUE, which you
+should  define  to  be  some  horrid  value  (definitely NOT 0).  This will
+encourage  all  code  that  relies on uninitialized memory to behave rather
+differently  when  Fortify  is  running.  If you ever see a pointer that is
+0xA7A7A7A7, you can be certain that it is uninitialized.
+
+
+    #define FORTIFY_FILL_ON_DEALLOCATE
+    #define FORTIFY_FILL_ON_DEALLOCATE_VALUE    0xA9
+
+    Programmers  often  try to use memory after they've freed it, which can
+sometimes  work  (so long as nobody else has modified the memory before you
+look  at  it), but is incredibly dangerous and definitely bad practice.  If
+FORTIFY_FILL_ON_DEALLOCATE  is defined, all memory you free will be stomped
+out  with  FORTIFY_FILL_ON_DEALLOCATE_VALUE, which ensures that any attempt
+to  read  freed  memory  will  give  incorrect  results.  If you ever see a
+pointer that is 0xA9A9A9A9, it definately came from free'd memory.
+
+
+    #define FORTIFY_FILL_ON_CORRUPTION
+
+    Fortify  will  never  free  memory  that  has  had  it's fortifications
+overwritten.   This  is  so that you have ample opportunity to examine this
+memory in a debugger.  If the memory remains corrupted, Fortify will report
+this  each  time  it  does  a  check  of memory, which can be annoying (but
+useful,  if  the  program  continues  to modify the memory).  If you define
+FORTIFY_FILL_ON_CORRUPTION,   Fortify   will   re-initialize   a  corrupted
+fortification  after  it  issues it's message.  Fortify will then no longer
+complain about this memory, until it is corrupted again.
+    This  has  the  extra  advantage  that software that tries to read this
+memory will probably break.
+
+
+    #define FORTIFY_CHECK_ALL_MEMORY_ON_ALLOCATE
+    #define FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE
+
+    CHECK_ALL_MEMORY_ON...   means  that for every single memory allocation
+or  deallocation,  every  single block of memory will be checked.  This can
+slow  down  programs considerably   if  you  have  a large number of blocks
+allocated.   You would normally only need to turn this on if you are trying
+to pinpoint where a corruption was occurring.
+    A  block  of  memory  is  always  checked  when  it  is  freed,  so  if
+CHECK_ALL...    isn't  turned  on,  corruptions  will  still  be  detected,
+eventually.
+    You  can  also  force  Fortify  to  check  all  memory  with  a call to
+Fortify_CheckAllMemory().   If you have a memory corruption you can't find,
+sprinkling  these  through the suspect code will help narrow it down.  When
+you get a message regarding a corruption, part of the output will be a line
+that  says  "Memory  integrity  was  last  verified  at  file.line".   This
+corresponds  to  when  the "CheckAllMemory" operation was last successfully
+performed,    either   automatically,   or   by   an   explicit   call   to
+Fortify_CheckAllMemory().
+
+
+    #define FORTIFY_PARANOID_DEALLOCATE
+
+    FORTIFY_PARANOID_DEALLOCATE  causes Fortify to traverse the memory list
+to  ensure  the  memory  you  are about to free was really allocated.  This
+option  is recommended in a protected memory operating system.  If a free()
+of  a  garbage  pointer  is attempted, Fortify will generate a segmentation
+fault  when  it  attempts  to checksum the memory pointed to by the garbage
+pointer.   If, however, FORTIFY_PARANOID_DELETE is on, Fortify will be able
+to  determine  that the pointer is garbage without crashing the system, and
+will be able to generate an error message.
+    Note  that  in  C++, however, if you try to "delete" a garbage pointer,
+you  will  most  likely crash before Fortify gets a look in.  When you do a
+"delete"  in  C++,  the first thing that happens is the object's destructor
+gets  called.  Depending on what the destructor actually does, it may crash
+due  to  having  a  bogus  "this".   The memory isn't freed until AFTER the
+destructor,  which  is  when  Fortify  would  be able to detect the invalid
+pointer  (too  late).   If  you are having problems with a weird crash in a
+destructor,  you may wish to add Fortify_CheckPointer(this) to the start of
+the  destructor,  but be warned that Fortify will generate an error message
+if you destruct an object that was created on the stack.
+    FORTIFY_PARANOID_DEALLOCATE  adds a small amount of overhead to freeing
+memory        (though        not        nearly       as       much       as
+FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE).  Paranoid mode would be quicker if
+Fortify  didn't  use a naive linked list to store it's memory on (see TO DO
+LIST, below).
+
+
+       #define FORTIFY_WARN_ON_ZERO_MALLOC
+       #define FORTIFY_FAIL_ON_ZERO_MALLOC
+
+       In  some  implementations,  a  malloc(0)  will  always  fail  (This  is
+non-ANSI).   If Fortify is turned on, malloc(0) won't actually reach malloc
+as  a  malloc(0)  -  Fortify adds fortifications, which means it won't be a
+zero byte allocation anymore, and will probably succeed.
+       Thus it is possible to write code that would work if Fortify was turned
+on,  but  fail  when Fortify is turned off.  If the version of malloc() you
+are   using   does   not  allow  malloc(0)  to  succeed,  you  must  enable
+FORTIFY_FAIL_ON_ZERO_MALLOC  to  enable  your  program to function properly
+with Fortify turned on.
+
+
+    #define FORTIFY_WARN_ON_ALLOCATE_FAIL
+
+    This  causes  a  debug to be issued whenever an allocation fails.  This
+can be very useful when identifying the cause for a crash.
+
+
+    #define FORTIFY_WARN_ON_FALSE_FAIL
+
+    A  debug  will  be  issued  when  an allocation is "false failed".  See
+Fortify_SetAllocateFailRate()  and  Fortify_SetAllocationLimit()  for  more
+information.
+
+    Fortify: A "malloc()" of 128 bytes "false failed" at test.c.27
+
+
+
+    #define FORTIFY_WARN_ON_SIZE_T_OVERFLOW
+
+    This  causes Fortify to check for breaking the size_t limit.  This is a
+problem  in  16-bit  applications  where  breaking  the  16  bit  limit  is
+reasonably likely.
+    The problem is that Fortify adds a small amount of overhead to a memory
+block;  so  in  a  16-bit size_t environment, if you tried to allocate 64K,
+Fortify  would  make  that  block bigger than 64K and your allocation would
+fail  due  to  the  presence of Fortify.  With size_t being 32 bits for all
+environments  worth  programming  in,  this  problem  is extremely unlikely
+(Unless you plan to allocate 4 gigabytes).
+
+
+    #define FORTIFY_AUTOMATIC_LOG_FILE
+    #define FORTIFY_LOG_FILENAME             "fortify.log"
+    #define FORTIFY_FIRST_ERROR_FUNCTION    cout << "\a\a\aOh Dear!\n"
+
+    If  FORTIFY_AUTOMATIC_LOG_FILE is defined (C++ only), then Fortify will
+output to a log file.  It will also automatically call Fortify_EnterScope()
+at program initialization, and Fortify_LeaveScope() at program termination.
+    If Fortify generated no output, the log file will not be altered.
+    FORTIFY_FIRST_ERROR_FUNCTION  will  be  called  upon  generation of the
+first  Fortify  message,  so that the user can tell if a Fortify report has
+been  generated.   Otherwise,  Fortify  would quietly write all this useful
+stuff out to the log file, and no-one would know to look there!
+    You  don't  need  to use Fortify_SetOutputFunc() at all if you're using
+the automatic log file.
+
+
+    #define FORTIFY_LOCK()
+    #define FORTIFY_UNLOCK()
+
+    In  a  multi-threaded  environment,  we need to arbitrate access to the
+fortify  memory list.  This is what FORTIFY_LOCK() and FORTIFY_UNLOCK() are
+used  for.  The calls to FORTIFY_LOCK() and FORTIFY_UNLOCK() must nest.  If
+no  two  threads/tasks/processes will be using the same Fortify at the same
+time,  then FORTIFY_LOCK() and FORTIFY_UNLOCK() can safely be #defined away
+to nothing.
+
+
+    #define FORTIFY_TRACK_DEALLOCATED_MEMORY
+    #define FORTIFY_DEALLOCATED_MEMORY_LIMIT 1048576
+    #define FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+    #define FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+
+    If  FORTIFY_TRACK_DEALLOCATED_MEMORY is enabled, Fortify won't actually
+free   memory   when  you  deallocate  it.   Freed  memory  goes  onto  the
+"deallocated"  list, where Fortify will keep an eye on it.  If you write to
+the  memory  after  it's  been freed, Fortify will be able to tell.  If you
+attempt to free memory twice, Fortify will be able to tell you for certain,
+rather than just suspect.
+    Deallocated  memory  tracking is only active if you've entered at least
+one  level  of  Fortify  scope.   This  is  so that Fortify will be able to
+actually free the deallocated memory when the scope is left.
+
+    Fortify: Write to deallocated block (0x75c4502,126,test.c.21)
+             detected at test.c.40
+             Memory block was deallocated by "realloc()" at test.c.34
+             Memory integrity was last verified at test.c.35
+    Address   Offset Data (a9)
+    0x75c4502      0 58a9a9a9 a9a9a9a9 a9a9a9a9 a9a9a9a9 "X"
+                     ...110 bytes skipped...
+
+    FORTIFY_DEALLOCATED_MEMORY_LIMIT,  if defined, is the maximum amount of
+memory  that  Fortify  should  keep  on  it's  deallocated  list.   If  you
+deallocate  some  memory,  and the total amount of deallocated memory being
+tracked is greater than this number, then Fortify will throw away (actually
+free)  the  oldest  chunks of memory, until it's under this threshold.  You
+don't  have to worry about running out of memory if this value is set high,
+Fortify  will  discard  deallocated  memory  in  preference  to  letting an
+allocation fail.  The main reason for this option is to restrict the amount
+of  time  spent  checking  freed  memory  for corruption.  
+    FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY  will  cause Fortify to
+issue  a  warning  whenever  it has to free some deallocated memory when it
+didn't  really  want  to.  If an allocation was going to fail, or if it was
+over  the FORTIFY_DEALLOCATED_MEMORY_LIMIT, and it had to free some memory,
+then  a warning would be issued.  Freeing deallocated memory when leaving a
+Fortify scope does not cause a warning.
+    FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY  is useful when
+you are trying to track down a particular write to some deallocated memory.
+Fortify  will  list  the details of all blocks being discarded, so that you
+can  tell  if  the  block  you  are interested in is still being watched by
+Fortify.
+    Note  that  Fortify  will  always  perform one last check on the memory
+before  it  discards it, so you can be sure that all memory being discarded
+is corruption free.
+
+    Fortify: Warning - Discarding deallocated memory at test.c.46
+                    (0x743e8b2,126,test.c.22,test.c.35)
+                    (0x743f0b2,456,test.c.32,test.c.46)
+
+
+
+    #define FORTIFY_DELETE_STACK_SIZE 256
+
+    Due  to  the  way  that  delete works, Fortify has to maintain it's own
+stack  of  delete  source-code  information.  For simplicity, this has been
+implemented  in a static array.  The size of this stack reflects the number
+of  levels  of  recursion that Fortify will be able to track during deletes
+(ie  deletes  being called from destructors called from a delete call).  If
+this  recursion  limit  is exceeded, Fortify will simply output the deepest
+sourcecode level known.  I think 256 levels should be ample.
+
+
+
+
+    typedef void (*Fortify_NewHandlerFunc)(void);
+    #define FORTIFY_NEW_HANDLER_FUNC Fortify_NewHandlerFunc
+
+    By  default,  Fortify  will  use  the  standard  new  handler  function
+prototype.   However,  some  non-standard compiler implementations (such as
+Microsoft  Visual  C++  2.0)  use  non-standard  prototypes  for  their new
+handlers.   FORTIFY_NEW_HANDLER_FUNC is the type that Fortify uses for it's
+new  handler function pointer.  Note that Fortify won't pass any parameters
+to  the  new  handler,  so  changing this is probably quite useless at this
+point in time.
+    
+
+
+    RUN TIME CONTROL
+    ----------------
+    Fortify  can  also  be  controlled  at  run  time  with  a  few special
+functions, which compile away to nothing if FORTIFY isn't defined.
+
+    Fortify_Disable()  -  Fortify  can be disabled at run-time.  Previously
+this   would   only   work   if   no  memory  was  allocated  at  the  time
+Fortify_Disable() was called, but in C++ environments, this is almost never
+possible.   After  Fortify_Disable()  has  been called, all new allocations
+will not be Fortified.  Deallocations will be treated slightly differently.
+Fortify  will  check to see if it allocated the memory, and if so, free it.
+If  not, it will pass it on to free().  Fortify_Disable() is useful to turn
+off Fortify if the overhead or bugs being induced by Fortify are getting in
+the  way.   To  correctly  remove  Fortify  for  software release, you must
+compile it out.
+       Note that once you've called Fortify_Disable(), there is no way to turn
+it back on again.
+
+    Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) - Sets the function
+used  to  output  all error and diagnostic messages by Fortify.  The output
+function takes a single (const char *) argument, and must be able to handle
+newlines.   The default output function is a printf() to stdout, unless you
+are using FORTIFY_AUTOMATIC_LOG_FILE, where the default is to output to the
+log file.  The function returns the old pointer.
+
+
+    Fortify_SetAllocateFailRate(int   Percent)   -  Fortify  will  make  an
+allocation attempt "fail" this "Percent" of the time, even if the memory IS
+available.  Useful to "stress-test" an application.  Returns the old value.
+The fail rate defaults to 0.
+
+
+    Fortify_SetAllocationLimit(unsigned  long  AllocationLimit)  - Impose a
+limit on the amount of memory the application can allocate.  This limit may
+be  changed  at  any  time.   If  you set this to 0, memory allocations are
+guaranteed  to  fail.   The  default is 0xffffffff, which is essentially no
+limit.   Returns the old value.  Fortify_GetCurrentAllocation() can be used
+to  find  out  how  much  memory  is  currently  allocated (see STATISTICAL
+FUNCTIONS, below).
+
+
+    DIAGNOSTIC FUNCTIONS
+    --------------------
+    Fortify also provides some additional diagnostic functions which can be
+used  to  track  down  memory  corruption  and memory leaks.  If Fortify is
+disabled,  these functions do nothing.  If calling these functions directly
+from  a debugger, remember to add the "const char *file" and "unsigned long
+line"  parameters  to  each  of  the calls (these are normally added by the
+preprocessor macros).
+
+ 
+    Fortify_CheckPointer(void *uptr) - Returns true if the uptr points to a
+valid block of allocated memory.  The memory must be on Fortify's list, and
+it's  sentinels must be in tact.  If anything is wrong, an error message is
+issued (if Fortify is disabled, this function always returns true).
+
+
+       Fortify_LabelPointer(void *uptr, const char *label) - Labels the memory
+block  with  a  string provided by the user.  This function takes a copy of
+the  passed  in  string.   The  pointer  MUST  be one returned by a Fortify
+allocation function.
+       This  function  can  be  very  useful  to track a memory block that was
+allocated  on  the  same  line as a bunch of other memory blocks.  Whenever
+Fortify  outputs  the information about this memory block, the label string
+will also be output.
+
+
+    Fortify_CheckAllMemory()  -  Checks  the  sentinels  of all memory that
+Fortify   knows   about.    This   includes   allocated   memory,   and  if
+FORTIFY_TRACK_DEALLOCATED_MEMORY  is turned on, any deallocated memory that
+Fortify  is  still  tracking.  Returns the number of blocks that failed (if
+Fortify is disabled, this function always returns 0).
+
+
+    Fortify_ListAllMemory()   -   Outputs  the  entire  list  of  currently
+allocated  memory.   For  each  block is output it's Address, Size, and the
+SourceFile  and Line that allocated it.  If there is no memory on the list,
+this function outputs nothing.  It returns the number of blocks on the list
+(if Fortify has been disabled, this function always returns 0).
+
+
+    Fortify_DumpAllMemory() - Outputs a hex dump of all currently allocated
+memory.
+
+
+    Fortify_EnterScope()  -  enters  a level of fortify scope.  Returns the
+new scope level.
+
+
+    Fortify_LeaveScope()  - leaves a level of fortify scope, it also prints
+a  dump  of all unfreed memory allocated within the scope being left.  This
+can  be  very  useful in tracking down memory leaks in a part of a program.
+If  you  place  a EnterScope/LeaveScope pair around a set of functions that
+should  have  no memory allocated when it's done, Fortify will let you know
+if  this  isn't the case.  Fortify will also discard any deallocated memory
+from the scope being left, if it is tracking deallocated memory.
+
+
+
+    STATISTICAL FUNCTIONS
+    ---------------------
+    Fortify gathers some basic statistics about your programs memory usage.
+It  will  keep  track  of  the total number of memory allocation operations
+performed, and also the maximum amount of memory allocated at any one time.
+
+    Fortify_OutputStatistics() - display the current statistics.
+
+    Fortify: Statistics at test.c.70
+             Maximum memory allocated at one time: 13633 bytes in 7 blocks
+             There have been 9 allocations and 4 deallocations
+             There was a total of 14343 bytes allocated
+             The average allocation was 1593 bytes
+
+
+    Fortify_GetCurrentAllocation()  -  returns  the  total amount of memory
+currently  allocated  by  the  application  (if  Fortify  is disabled, this
+function will always return 0).
+
+
+
+
+    PROBLEMS WITH THE new AND delete MACROS
+    ---------------------------------------
+    Due  to  limitations  of the C preprocessor, getting caller source-code
+information  to  new  and  delete  isn't  as easy as it is for malloc() and
+free().   The macro for "new" which adds this information onto the new call
+causes  syntax  errors  if  you  try to declare a custom new operator.  The
+actual  Fortifying  works  fine, it's just the macro expansion which causes
+problems.
+    If  this  happens,  the  easiest  thing  to do is #ifdef out the custom
+new/delete  operators  if  FORTIFY  is defined.  Alternatively, you can not
+#include  "fortify.h"  for the offending file (and any files that use these
+custom   operators,   but   remember   that  they  won't  have  source-code
+information).
+
+    eg.
+    #ifndef FORTIFY /* can't easily use custom new's with FORTIFY enabled */
+    void *X::operator new(size_t size) { return malloc(size); }
+    #endif
+
+    Due  to a limitation with delete (it is illegal to declare a version of
+delete  that  takes  different parameters), Fortify has limited information
+about  where  delete  is  being called from, and so the the line and source
+information  will  often  say  "delete.0". If  a delete is occurring from 
+within  another delete, Fortify is now able to maintain a 'delete stack',
+and will output this stack after the main body of the Fortify hit.
+
+
+
+
+    WHEN TO USE FORTIFY
+    -------------------
+    You  should  never  be without Fortify when you're developing software.
+It will detect your bugs _as_you_write_them_, which makes them a lot easier
+to find.
+    Leave  Fortify  enabled  until  the  final  test  and  release  of your
+software.   You  probably  won't  want  some of the slower options, such as
+CHECK_ALL_MEMORY_ON_DEALLOCATE.   With  the  exception  of  those  options,
+Fortify  doesn't have a great deal of overhead.  If posing a great problem,
+this  overhead  can  be  reduced  by  cutting  down  on  the  size  of  the
+fortifications, and turning off the pre/post fills, but each thing you turn
+off gives Fortify less information to work with in tracking your bugs.
+       (And besides, the slower your program runs while you're developing it,
+the more efficient your algorithms are likely to be!).
+
+
+    Dynamic Link Libraries
+       ----------------------
+       Dynamic  Linking  of the standard libraries will not work with Fortify.
+The  standard library DLL has it's own copy of memory management functions,
+so any memory allocated by the DLL will be unknown to Fortify, and you will
+get erroneous error messages.
+
+       If  you are writing your own DLL's, or using a 3rd party one, it may be
+possible  to  write  a callback module to get the DLL's to call the Fortify
+routines  in  the  parent application.  If anyone does write a module to do
+this, please send it to me so I can include it in the next version.
+
+       If  the  DLL  doesn't  allocate any memory, or your application doesn't
+call  free/delete/realloc  on any memory allocated by the DLL, then Fortify
+should work fine.
+
+       Another  alternative to the DLL problem is to use normal link libraries
+while  you  are developing with Fortify, and then rebuild them as DLL's for
+release.  This of course may not be appropriate in all situations.
+
+
+
+    REVISION HISTORY
+    ----------------
+
+Changes from V2.1 to V2.2
+       Added  FORTIFY_WARN_ON_ZERO_MALLOC, and FORTIFY_FAIL_ON_ZERO_MALLOC, as
+some compilers do not allow a malloc(0) to succeed.
+       Fixed a couple of incorrect #ifdef's.
+       Improved some of the documentation.
+       Fortify_LabelPointer() misbehaved when Fortify had been run-time
+disabled.
+
+Changes from V2.0 to V2.1
+       Fixed Fortify_LabelPointer(), which was broken.
+
+
+Changes from V2.0B to V2.0
+
+    Moved  the  checksum  to  the  start  of the Header, to avoid alignment
+problems (thanks to Ron Flory and Tim Taylor for finding this)
+    Fixed a miscalcultation with FORTIFY_ALIGNED_BEFORE_SIZE (thanks to Tim
+Taylor)
+    Implemented  the  delete stack - Fortify is now aware of deletes inside
+deletes, and outputs the full delete stack with all delete related hits.
+    Implemented  the  new  and  improved  Fortify_Disable() - works even if
+memory has already been allocated.
+    Fixed a few problems with FORTIFY_TRACK_DEALLOCATED_MEMORY being turned
+off.
+    Fixed a couple of incorrect sprintfs.
+       Added Fortify_LabelPointer (thanks to Steve Toal for this idea)
+       FORTIFY_WARN_ON_ZERO_ALLOCATE  removed  as "new char[0]" is allowed, as
+is malloc(0).
+    free(0) is now accepted as harmless.
+
+
+
+Changes from V1.0 to V2.0 B
+
+    Added  FORTIFY_ALIGNMENT,  so that machines requiring special alignment
+wouldn't break.
+    Added  deallocated  memory  tracking,  and  loads  of  diagnostics made
+possible by this.
+    Added statistics.
+    Merged Fortify and ZFortify.
+    Each  memory  block  now  knows  which  allocator  function was used to
+allocate  it,  and  uses this information to ensure the correct function is
+being used to free it.
+    Added support for strdup()
+    Added support for versions of sprintf that don't support "%p".
+    Fortify  will  now  supply  default values for configuration parameters
+missing from "ufortify.h"
+    A few minor portability bug fixes
+    Fortify will now automatically configure itself for GCC and Borland C++
+4.5.
+    All  error  messages  and  warnings  tidied  up  so  they are easier to
+understand.
+    The new operators will now call the new handler if the allocation fails
+(if there is a new handler installed, of course).
+
+
+Changes from SafeMem to Fortify V1.0
+
+    Completely rewrote it.
+    Fortifies ANSI memory allocation functions rather than Amiga OS ones.
+    Supports C++'s new and delete
+
+
+
+
+    TO DO
+    -----
+    Make Fortify automatically configure itself for major compilers.
+
+    Add support for non-standard new-handlers, such as Microsoft Visual C++
+2.0, via FORTIFY_NEW_HANDLER_FUNC.
+
+    Implement a stack for scope source-code info and scoped statistics.
+
+    Better documentation.
+
+    FAQ  -  installation  problems,  linking  problems,  "spurious output",
+understanding the results, how to track down hits.
+
+    Better test programs (with examples of obscure bugs).
+
+    Memory  allocation  list could be implemented as a "skip list", so that
+searching would be quicker.  "Paranoid" mode would be quite fast.
+
+    CHECK_ALL_MEMORY_ON_  could take a percentage of the time to do it - it
+could  be set to 50%, so that memory is only checked 1/2 of the time, or we
+only  check 1/2 of the memory, or something like that, so that the checking
+still  goes  on,  but less frequently, so there is less overhead.  Probably
+overkill.
+
+       Write  a  DLL  callback module so that user DLL's can share memory with
+their parent applicatoins.
+
+       Add a "pass-count" to source-code information.
+
diff --git a/frontends/amiga/fortify/MAKEFILE b/frontends/amiga/fortify/MAKEFILE
new file mode 100755
index 0000000..0c1cc86
--- /dev/null
+++ b/frontends/amiga/fortify/MAKEFILE
@@ -0,0 +1,48 @@
+#
+# GCC makefile for Fortify's test applications
+# Disable -DFORTIFY to compile without Fortify
+#
+# To build both of the testers, it should simply be
+# a matter of
+#
+#             make all
+#
+#
+
+.SUFFIXES: .cxx .cpp
+
+CC      = gcc
+CCFLAGS = -Wall -DFORTIFY -Wformat -pedantic
+LN      = gcc
+LNFLAGS = -lm -liostream
+
+.c.o:
+       @echo ---- $*.c ----
+       @$(CC) -c $(CCFLAGS) $*.c
+
+.cxx.o:
+       @echo ---- $*.cxx ----
+       @$(CC) -c $(CCFLAGS) $*.cxx
+
+#.cpp.o:
+#      @echo ---- $*.cpp ----
+#      @$(CC) -c $(CCFLAGS) $*.cpp
+
+all: test test2
+
+OBJS= test.o fortify.o
+test: $(OBJS)
+       @echo Linking test
+       @$(LN) -o test $(OBJS) $(CCFLAGS) $(LNFLAGS)
+
+OBJS2 = test2.o fortify.o
+test2: $(OBJS2)
+       @echo Linking test2
+       @$(LN) -o test2 $(OBJS2) $(CCFLAGS) $(LNFLAGS)
+
+
+fortify.o: fortify.cxx fortify.h ufortify.h
+
+test.o: test.c fortify.h ufortify.h
+
+test2.o: test2.cxx fortify.h ufortify.h
diff --git a/frontends/amiga/fortify/TEST.C b/frontends/amiga/fortify/TEST.C
new file mode 100755
index 0000000..a6e9c43
--- /dev/null
+++ b/frontends/amiga/fortify/TEST.C
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "fortify.h"
+
+/*
+ * NOTE: The Fortify routines will compile away to nothing
+ * if FORTIFY isn't defined in the makefile.
+ *
+ * DO NOT insert #define FORTIFY here. It Will Not Work.
+ * All files (including fortify.cxx) need FORTIFY to be
+ * defined. The correct place for this is the makefile.
+ */
+
+
+int
+main(int argc, char **argv)
+{                   
+       char *foo, *bar;
+   
+    Fortify_EnterScope();
+
+       /* note that we never free this memory */
+       foo = malloc(123);
+
+       Fortify_LabelPointer(foo, "we never free this memory!");
+
+       /* note that we read this memory after it's been freed */       
+       foo = malloc(124);
+       *foo = 'X';
+       free(foo);
+       printf("Should be X: '%c'\n", *foo);
+
+       /* note we've already freed this memory */      
+       free(foo);
+       
+       /* note we write to memory that's been realloc'd, using the old pointer 
*/
+       foo = malloc(125);
+       bar = realloc(foo, 126);
+       *foo = 'X';
+       free(bar);      
+       
+       /* note we write before the block */
+       foo = malloc(127);
+       Fortify_LabelPointer(foo, "we write before this block!");
+       *(foo-1) = 'Z';
+       free(foo);
+       
+       /* note we write after the block */
+       bar = "I'm going to eat you little fishie!";
+       foo = malloc(strlen(bar));
+       strcpy(foo, bar);
+       free(foo);
+
+       /* we never allocated this memory */
+       free(bar);      
+
+       Fortify_LeaveScope();
+       Fortify_OutputStatistics(); 
+
+       return 42;
+}
diff --git a/frontends/amiga/fortify/TEST2.CXX 
b/frontends/amiga/fortify/TEST2.CXX
new file mode 100755
index 0000000..dc1dfcd
--- /dev/null
+++ b/frontends/amiga/fortify/TEST2.CXX
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fortify.h"
+
+/*
+ * NOTE: The Fortify routines will compile away to nothing
+ * if FORTIFY isn't defined in the makefile.
+ *
+ * DO NOT insert #define FORTIFY here. It Will Not Work.
+ * All files (including fortify.cxx) need FORTIFY to be
+ * defined. The correct place for this is the makefile.
+ */
+
+class A
+{
+public:
+       ~A() { delete (char*)123; }
+};
+
+int
+main(int argc, char **argv)
+{                   
+       char *foo;
+                   
+    Fortify_EnterScope();               
+
+       /* zero size test */
+       foo =(char*) malloc(0);
+       printf("malloc(0) %s\n", foo ? "succeeded" : "failed");
+
+       /* zero size test */
+       foo = new char[0];
+       printf("new char[0] %s\n", foo ? "succeeded" : "failed");
+
+                   
+       foo = new char;
+
+       /* note we use the incorrect deallocator */
+       /* note this will only be detected if FORTIFY_PROVIDE_ARRAY_NEW
+     * and FORTIFY_PROVIDE_ARRAY_DELETE are both turned on
+     * (and your compiler supports them) */
+       delete[] foo;
+       *foo = 'Z';
+
+       foo = new char;
+       Fortify_LabelPointer(foo, "we use the wrong deallocator on this one");
+
+       /* note we use the incorrect dealocator */
+       free(foo);
+
+       /* the destructor of this class does an illegal delete -
+        * demonstrates the delete-stack
+        */
+       delete new A;
+
+       Fortify_LeaveScope();
+
+       return 1;
+}
diff --git a/frontends/amiga/fortify/fortify.c 
b/frontends/amiga/fortify/fortify.c
new file mode 100755
index 0000000..8a4f16c
--- /dev/null
+++ b/frontends/amiga/fortify/fortify.c
@@ -0,0 +1,2296 @@
+/* fortify.cxx - A fortified memory allocation shell - V2.2 */
+
+/*
+ *     This  software  is  not public domain.  All material in
+ * this  archive  is (C) Copyright 1995 Simon P.  Bullen.  The
+ * software  is  freely distributable, with the condition that
+ * no   more   than  a  nominal  fee  is  charged  for  media.
+ * Everything  in  this distribution must be kept together, in
+ * original, unmodified form.
+ *     The software may be modified for your own personal use,
+ * but modified files may not be distributed.
+ *     The  material  is  provided "as is" without warranty of
+ * any  kind.  The author accepts no responsibility for damage
+ * caused by this software.
+ *     This  software  may not be used in any way by Microsoft
+ * Corporation  or  its  subsidiaries, or current employees of
+ * Microsoft Corporation or its subsidiaries.
+ *     This  software  may  not  be used for the construction,
+ * development,  production,  or  testing of weapon systems of
+ * any kind.
+ *     This  software  may  not  be used for the construction,
+ * development,  production,  or  use  of plants/installations
+ * which  include  the  processing  of radioactive/fissionable
+ * material.
+ */
+
+/*  
+ *     If  you use this software at all, I'd love to hear from
+ * you.   All  questions,  criticisms, suggestions, praise and
+ * postcards are most welcome.
+ * 
+ *            email:    [email protected]
+ * 
+ *            snail:    Simon P. Bullen
+ *                      PO BOX 12138
+ *                      A'Beckett St.
+ *                      Melbourne 3000
+ *                      Australia
+ */
+
+#ifdef FORTIFY
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include <ctype.h>
+#include <time.h>
+
+
+/* the user's options */
+#include "ufortify.h"
+
+/* Prototypes and such */
+#define __FORTIFY_C__
+#include "fortify.h"
+
+
+/*
+ * Round x up to the nearest multiple of n.
+ */
+#define ROUND_UP(x, n) ((((x) + (n)-1)/(n))*(n))
+
+/*
+ * struct Header - this structure is used 
+ * internally by Fortify to manage it's 
+ * own private lists of memory.
+ */
+struct Header
+{
+    unsigned short Checksum;    /* For the integrity of our goodies  */
+    const char    *File;        /* The sourcefile of the allocator   */
+    unsigned long  Line;        /* The sourceline of the allocator   */
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    const char    *FreedFile;   /* The sourcefile of the deallocator */
+    unsigned long  FreedLine;   /* The sourceline of the deallocator */
+    unsigned char  Deallocator; /* The deallocator used              */
+#endif
+    size_t         Size;        /* The size of the malloc'd block    */
+    struct Header *Prev;        /* Previous link                     */
+    struct Header *Next;        /* Next link                         */
+    char          *Label;              /* User's Label (may be null)        */
+    unsigned char  Scope;       /* Scope level of the caller         */
+    unsigned char  Allocator;   /* malloc/realloc/new/etc            */
+};
+
+#define FORTIFY_HEADER_SIZE ROUND_UP(sizeof(struct Header), sizeof(unsigned 
short))
+
+
+
+/*
+ * FORTIFY_ALIGNED_BEFORE_SIZE is FORTIFY_BEFORE_SIZE rounded up to the
+ * next multiple of FORTIFY_ALIGNMENT. This is so that we can guarantee
+ * the alignment of user memory for such systems where this is important
+ * (eg storing doubles on a SPARC)
+ */
+#define FORTIFY_ALIGNED_BEFORE_SIZE ( \
+                   ROUND_UP(FORTIFY_HEADER_SIZE + FORTIFY_BEFORE_SIZE, 
FORTIFY_ALIGNMENT) \
+                   - FORTIFY_HEADER_SIZE)
+
+/*
+ * FORTIFY_OVERHEAD is the total overhead added by Fortify to each
+ * memory block.
+ */
+#define FORTIFY_OVERHEAD ( FORTIFY_HEADER_SIZE \
+                         + FORTIFY_ALIGNED_BEFORE_SIZE \
+                         + FORTIFY_AFTER_SIZE) 
+
+
+/*
+ *
+ * Static Function Prototypes
+ *
+ */
+static int  st_CheckBlock(struct Header *h, const char *file, unsigned long 
line);
+static int  st_CheckFortification (unsigned char *ptr, unsigned char value, 
size_t size);
+static void st_SetFortification   (unsigned char *ptr, unsigned char value, 
size_t size);
+static void st_OutputFortification(unsigned char *ptr, unsigned char value, 
size_t size);
+static void st_HexDump(unsigned char *ptr, size_t offset, size_t size, int 
title);
+static int  st_IsHeaderValid(struct Header *h);
+static void st_MakeHeaderValid(struct Header *h);
+static unsigned short st_ChecksumHeader(struct Header *h);
+static int  st_IsOnAllocatedList(struct Header *h);
+static void st_OutputHeader(struct Header *h);
+static void st_OutputMemory(struct Header *h);
+static void st_OutputLastVerifiedPoint(void);
+static void st_DefaultOutput(const char *String);
+static const char *st_MemoryBlockString(struct Header *h);
+static void st_OutputDeleteTrace();
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+#ifdef FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+#ifdef FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+    static const char *st_DeallocatedMemoryBlockString(struct Header *h);
+#endif /* FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+#endif /* FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+    static int  st_IsOnDeallocatedList(struct Header *h);
+    static int st_PurgeDeallocatedBlocks(unsigned long Bytes, const char 
*file, unsigned long line);
+    static int st_PurgeDeallocatedScope(unsigned char Scope, const char *file, 
unsigned long line);
+    static int st_CheckDeallocatedBlock(struct Header *h, const char *file, 
unsigned long line);
+    static void st_FreeDeallocatedBlock(struct Header *h, const char *file, 
unsigned long line);
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+
+/*
+ *
+ * Static variables
+ *
+ */
+static struct Header *st_AllocatedHead   = 0;
+static int  st_AllocateFailRate = 0;
+static char st_Buffer[256];
+static Fortify_OutputFuncPtr st_Output    = st_DefaultOutput;
+static const char    *st_LastVerifiedFile = "unknown";
+static unsigned long  st_LastVerifiedLine = 0;
+static unsigned char  st_Scope            = 0;
+static unsigned char  st_Disabled = 0;
+
+#ifdef __cplusplus
+    int                   gbl_FortifyMagic = 0;
+    static const    char *st_DeleteFile[FORTIFY_DELETE_STACK_SIZE];
+    static unsigned long  st_DeleteLine[FORTIFY_DELETE_STACK_SIZE];
+    static unsigned long  st_DeleteStackTop;
+#endif /* __cplusplus */
+
+/* statistics */
+static unsigned long  st_MaxBlocks        = 0;
+static unsigned long  st_MaxAllocation    = 0;
+static unsigned long  st_CurBlocks        = 0;
+static unsigned long  st_CurAllocation    = 0;
+static unsigned long  st_Allocations      = 0;
+static unsigned long  st_Frees            = 0;
+static unsigned long  st_TotalAllocation  = 0;
+static unsigned long  st_AllocationLimit  = 0xffffffff;
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    static struct Header *st_DeallocatedHead = 0;
+    static struct Header *st_DeallocatedTail = 0;
+    static unsigned long  st_TotalDeallocated = 0;
+#endif
+
+ 
+/* allocators */
+static const char *st_AllocatorName[] =
+{
+    "malloc()",
+    "calloc()",
+    "realloc()",
+    "strdup()",
+    "new",
+    "new[]"
+};
+
+/* deallocators */
+static const char *st_DeallocatorName[] =
+{
+    "nobody",
+    "free()",
+    "realloc()",
+    "delete",
+    "delete[]"
+};
+
+static const unsigned char st_ValidDeallocator[] =
+{
+    (1<<Fortify_Deallocator_free) | (1<<Fortify_Deallocator_realloc),
+    (1<<Fortify_Deallocator_free) | (1<<Fortify_Deallocator_realloc),
+    (1<<Fortify_Deallocator_free) | (1<<Fortify_Deallocator_realloc),
+    (1<<Fortify_Deallocator_free) | (1<<Fortify_Deallocator_realloc),
+#if defined(FORTIFY_PROVIDE_ARRAY_NEW) && defined(FORTIFY_PROVIDE_ARRAY_DELETE)
+    (1<<Fortify_Deallocator_delete),
+    (1<<Fortify_Deallocator_array_delete)
+#else
+    (1<<Fortify_Deallocator_delete) | (1<<Fortify_Deallocator_array_delete),
+    (1<<Fortify_Deallocator_delete) | (1<<Fortify_Deallocator_array_delete)
+#endif
+};
+
+
+/*
+ * Fortify_Allocate() - allocate a block of fortified memory
+ */
+void *FORTIFY_STORAGE
+Fortify_Allocate(size_t size, unsigned char allocator, const char *file, 
unsigned long line)
+{
+    unsigned char *ptr;
+    struct Header *h;
+    int another_try;
+
+    /* 
+     * If Fortify has been disabled, then it's easy
+     */
+    if(st_Disabled)
+    {
+#ifdef FORTIFY_FAIL_ON_ZERO_MALLOC
+       if(size == 0 && (allocator == Fortify_Allocator_new
+                      || allocator == Fortify_Allocator_array_new))
+               {
+                       /*
+                        * A new of zero bytes must succeed, but a malloc of 
+             * zero bytes probably won't
+             */
+                       return malloc(1);
+               }
+#endif
+
+        return malloc(size);
+    }
+
+#ifdef FORTIFY_CHECK_ALL_MEMORY_ON_ALLOCATE
+    Fortify_CheckAllMemory(file, line);
+#endif  
+
+    if(st_AllocateFailRate > 0)
+    {
+        if(rand() % 100 < st_AllocateFailRate)
+        {
+#ifdef FORTIFY_WARN_ON_FALSE_FAIL
+            sprintf(st_Buffer, 
+                    "\nFortify: A \"%s\" of %lu bytes \"false failed\" at 
%s.%lu\n",
+                    st_AllocatorName[allocator], (unsigned long)size, file, 
line);
+            st_Output(st_Buffer);
+#endif
+            return(0);
+        }
+    }
+
+    /* Check to see if this allocation will 
+     * push us over the artificial limit
+     */
+    if(st_CurAllocation + size > st_AllocationLimit)
+    {
+#ifdef FORTIFY_WARN_ON_FALSE_FAIL
+        sprintf(st_Buffer, 
+                "\nFortify: A \"%s\" of %lu bytes \"false failed\" at 
%s.%lu\n",
+                st_AllocatorName[allocator], (unsigned long)size, file, line);
+        st_Output(st_Buffer);
+#endif
+        return(0);
+    }
+
+#ifdef FORTIFY_WARN_ON_ZERO_MALLOC
+       if(size == 0 && (allocator == Fortify_Allocator_malloc ||
+                     allocator == Fortify_Allocator_calloc ||
+                     allocator == Fortify_Allocator_realloc ))
+       {                     
+               sprintf(st_Buffer, 
+                       "\nFortify: A \"%s\" of 0 bytes attempted at %s.%lu\n",
+                st_AllocatorName[allocator], file, line);
+               st_Output(st_Buffer);
+       }
+#endif /* FORTIFY_WARN_ON_ZERO_MALLOC */
+
+#ifdef FORTIFY_FAIL_ON_ZERO_MALLOC
+       if(size == 0 && (allocator == Fortify_Allocator_malloc ||
+                     allocator == Fortify_Allocator_calloc ||
+                     allocator == Fortify_Allocator_realloc ))
+       {                     
+#ifdef FORTIFY_WARN_ON_ALLOCATE_FAIL
+        sprintf(st_Buffer, "\nFortify: A \"%s\" of %lu bytes failed at 
%s.%lu\n",
+                st_AllocatorName[allocator], (unsigned long)size, file, line);
+        st_Output(st_Buffer);
+#endif /* FORTIFY_WARN_ON_ALLOCATE_FAIL */
+               return 0;
+       }
+#endif /* FORTIFY_FAIL_ON_ZERO_MALLOC */       
+
+#ifdef FORTIFY_WARN_ON_SIZE_T_OVERFLOW
+    /*
+     * Ensure the size of the memory block
+     * plus the overhead isn't bigger than
+     * size_t (that'd be a drag)
+     */
+    {
+        size_t private_size = FORTIFY_HEADER_SIZE
+                            + FORTIFY_ALIGNED_BEFORE_SIZE + size + 
FORTIFY_AFTER_SIZE;
+
+        if(private_size < size)
+        {
+            sprintf(st_Buffer, 
+                    "\nFortify: A \"%s\" of %lu bytes has overflowed size_t at 
%s.%lu\n",
+                    st_AllocatorName[allocator], (unsigned long)size, file, 
line);
+            st_Output(st_Buffer);
+            return(0);
+        }                              
+    }
+#endif                              
+
+    another_try = 1;
+    do
+    {
+        /*
+         * malloc the memory, including the space 
+         * for the header and fortification buffers
+         */  
+        ptr = (unsigned char *)malloc(  FORTIFY_HEADER_SIZE
+                                      + FORTIFY_ALIGNED_BEFORE_SIZE 
+                                      + size
+                                      + FORTIFY_AFTER_SIZE );
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+        /*
+         * If we're tracking deallocated memory, then
+         * we can free some of it, rather than let
+         * this malloc fail
+         */
+        if(!ptr)
+        {
+            another_try = st_PurgeDeallocatedBlocks(size, file, line);
+        }
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+    }
+    while(!ptr && another_try);
+
+    if(!ptr)
+    {
+#ifdef FORTIFY_WARN_ON_ALLOCATE_FAIL
+        sprintf(st_Buffer, "\nFortify: A \"%s\" of %lu bytes failed at 
%s.%lu\n",
+                st_AllocatorName[allocator], (unsigned long)size, file, line);
+        st_Output(st_Buffer);
+#endif
+        return(0);       
+    }
+
+    /*
+     * Begin Critical Region
+     */
+    FORTIFY_LOCK();
+
+
+    /* 
+     * Make the head's prev pointer point to us
+     * ('cos we're about to become the head)
+     */
+    if(st_AllocatedHead)
+    {
+        st_CheckBlock(st_AllocatedHead, file, line);
+        /* what should we do if this fails? (apart from panic) */
+
+        st_AllocatedHead->Prev = (struct Header *)ptr;
+        st_MakeHeaderValid(st_AllocatedHead);  
+    }
+
+    /*
+     * Initialize and validate the header
+     */
+    h = (struct Header *)ptr;
+    h->Size      = size;
+    h->File      = file;
+    h->Line      = line;  
+    h->Next      = st_AllocatedHead;
+    h->Prev      = 0;
+    h->Scope     = st_Scope;
+    h->Allocator = allocator;
+    h->Label     = 0;
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    h->FreedFile = 0;
+    h->FreedLine = 0;
+    h->Deallocator = Fortify_Deallocator_nobody;
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+    st_MakeHeaderValid(h);
+    st_AllocatedHead = h;
+  
+    /*
+     * Initialize the fortifications
+     */    
+    st_SetFortification(ptr + FORTIFY_HEADER_SIZE,
+                     FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
+    st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + size,
+                     FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
+
+#ifdef FORTIFY_FILL_ON_ALLOCATE
+    /*
+     * Fill the actual user memory
+     */
+    st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                        FORTIFY_FILL_ON_ALLOCATE_VALUE, size);
+#endif
+
+    /*
+     * End Critical Region
+     */
+    FORTIFY_UNLOCK();
+
+
+    /*
+     * update the statistics
+     */
+    st_TotalAllocation += size;
+    st_Allocations++;
+    st_CurBlocks++;
+    st_CurAllocation += size;
+    if(st_CurBlocks > st_MaxBlocks)
+        st_MaxBlocks = st_CurBlocks;
+    if(st_CurAllocation > st_MaxAllocation)
+        st_MaxAllocation = st_CurAllocation;
+
+    /*
+     * We return the address of the user's memory, not the start of the block,
+     * which points to our magic cookies
+     */
+    return(ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE);
+}
+
+
+
+/*
+ * Fortify_Deallocate() - Free a block of memory allocated with 
Fortify_Allocate()
+ */
+void FORTIFY_STORAGE
+Fortify_Deallocate(void *uptr, unsigned char deallocator, const char *file, 
unsigned long line)
+{
+    unsigned char *ptr = (unsigned char *)uptr
+                        - FORTIFY_HEADER_SIZE
+                        - FORTIFY_ALIGNED_BEFORE_SIZE;
+    struct Header *h   = (struct Header *)ptr;
+
+#ifdef FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE
+    Fortify_CheckAllMemory(file, line);
+#endif
+
+    /*
+     * If Fortify has been disabled, then it's easy
+     * (well, almost)
+     */
+    if(st_Disabled)
+    {
+        /* there is a possibility that this memory
+         * block was allocated when Fortify was
+         * enabled, so we must check the Allocated
+         * list before we free it.
+         */
+        if(!st_IsOnAllocatedList(h))
+        {
+            free(uptr);    
+            return;
+        }    
+        else
+        {
+            /* the block was allocated by Fortify, so we 
+             * gotta free it differently.
+             */
+            /*
+             * Begin critical region
+             */
+            FORTIFY_LOCK();
+        
+            /*
+             * Remove the block from the list
+             */
+            if(h->Prev)
+                h->Prev->Next = h->Next;
+            else
+                st_AllocatedHead = h->Next;
+        
+            if(h->Next)
+                h->Next->Prev = h->Prev;
+        
+            /*
+             * End Critical Region
+             */
+            FORTIFY_UNLOCK();
+
+            /*
+             * actually free the memory
+             */
+            free(ptr);
+            return;
+        }
+    }
+
+
+#ifdef FORTIFY_PARANOID_DEALLOCATE
+    if(!st_IsOnAllocatedList(h))
+    {
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+        if(st_IsOnDeallocatedList(h))
+        {
+            sprintf(st_Buffer, "\nFortify: \"%s\" twice of %s detected at 
%s.%lu\n",
+                                st_DeallocatorName[deallocator],
+                                st_MemoryBlockString(h), file, line);
+            st_Output(st_Buffer);
+
+            sprintf(st_Buffer, "         Memory block was deallocated by 
\"%s\" at %s.%lu\n",
+                                st_DeallocatorName[h->Deallocator], 
h->FreedFile, h->FreedLine);
+            st_Output(st_Buffer);
+            st_OutputDeleteTrace();
+            return;
+        }
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+#ifdef FORTIFY_NO_PERCENT_P
+        sprintf(st_Buffer, "\nFortify: Possible \"%s\" twice of (0x%08lx) was 
detected at %s.%lu\n",
+#else
+        sprintf(st_Buffer, "\nFortify: Possible \"%s\" twice of (%p) was 
detected at %s.%lu\n",
+#endif
+                            st_DeallocatorName[deallocator],
+                            uptr, file, line);
+        st_Output(st_Buffer);
+        st_OutputDeleteTrace();
+        return;
+    }
+#endif /* FORTIFY_PARANOID_DELETE */
+
+    /*
+     * Make sure the block is okay before we free it.
+     * If it's not okay, don't free it - it might not
+     * be a real memory block. Or worse still, someone
+     * might still be writing to it
+     */
+    if(!st_CheckBlock(h, file, line))
+    {
+        st_OutputDeleteTrace();
+        return;
+    }
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    /*
+     * Make sure the block hasn't been freed already
+     * (we can get to here if FORTIFY_PARANOID_DELETE
+     * is off, but FORTIFY_TRACK_DEALLOCATED_MEMORY
+     * is on).
+     */
+    if(h->Deallocator != Fortify_Deallocator_nobody)
+    {
+        sprintf(st_Buffer, "\nFortify: \"%s\" twice of %s detected at 
%s.%lu\n",
+                              st_DeallocatorName[deallocator],
+                            st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+
+        sprintf(st_Buffer, "         Memory block was deallocated by \"%s\" at 
%s.%lu\n",
+                            st_DeallocatorName[h->Deallocator], h->FreedFile, 
h->FreedLine);
+        st_Output(st_Buffer);
+        st_OutputDeleteTrace();
+        return;
+    }
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+    /*
+     * Make sure the block is being freed with a valid
+     * deallocator. If not, complain. (but free it anyway)
+     */
+    if((st_ValidDeallocator[h->Allocator] & (1<<deallocator)) == 0)
+    {
+        sprintf(st_Buffer, "\nFortify: Incorrect deallocator \"%s\" detected 
at %s.%lu\n",
+                              st_DeallocatorName[deallocator], file, line);
+        st_Output(st_Buffer);
+        sprintf(st_Buffer,   "         %s was allocated with \"%s\"\n",
+                              st_MemoryBlockString(h), 
st_AllocatorName[h->Allocator]);
+        st_Output(st_Buffer);
+        st_OutputDeleteTrace();
+    }
+
+    /*
+     * Begin critical region
+     */
+    FORTIFY_LOCK();
+
+    /*
+     * Remove the block from the list
+     */
+    if(h->Prev)
+    {
+        if(!st_CheckBlock(h->Prev, file, line))
+        {
+            FORTIFY_UNLOCK();
+            st_OutputDeleteTrace();
+            return;
+        }
+
+        h->Prev->Next = h->Next;
+        st_MakeHeaderValid(h->Prev);
+    }
+    else
+        st_AllocatedHead = h->Next;
+
+    if(h->Next)
+    {
+        if(!st_CheckBlock(h->Next, file, line))
+        {
+            FORTIFY_UNLOCK();
+            st_OutputDeleteTrace();
+            return;
+        }
+
+        h->Next->Prev = h->Prev;
+        st_MakeHeaderValid(h->Next);
+    }
+
+    /*
+     * End Critical Region
+     */
+    FORTIFY_UNLOCK();
+
+    /*
+     * update the statistics
+     */
+    st_Frees++;
+    st_CurBlocks--;
+    st_CurAllocation -= h->Size;
+
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    if(st_Scope > 0)
+    {
+        /*
+         * Don't _actually_ free the memory block, just yet.
+         * Place it onto the deallocated list, instead, so
+         * we can check later to see if it's been written to.
+         */
+    #ifdef FORTIFY_FILL_ON_DEALLOCATE
+        /*
+         * Nuke out all user memory that is about to be freed
+         */
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                                    FORTIFY_FILL_ON_DEALLOCATE_VALUE,
+                                  h->Size);
+    #endif /* FORTIFY_FILL_ON_DEALLOCATE */
+
+        /*
+         * Begin critical region
+         */
+        FORTIFY_LOCK();
+
+        /*
+         * Place the block on the deallocated list
+         */
+        if(st_DeallocatedHead)
+        {
+            st_DeallocatedHead->Prev = (struct Header *)ptr;
+            st_MakeHeaderValid(st_DeallocatedHead);
+        }
+
+        h = (struct Header *)ptr;
+        h->FreedFile   = file;
+        h->FreedLine   = line;
+        h->Deallocator = deallocator;
+        h->Next        = st_DeallocatedHead;
+        h->Prev        = 0;
+        st_MakeHeaderValid(h);
+        st_DeallocatedHead = h;
+
+        if(!st_DeallocatedTail)
+        {
+            st_DeallocatedTail = h;
+        }
+
+        st_TotalDeallocated += h->Size;
+
+    #ifdef FORTIFY_DEALLOCATED_MEMORY_LIMIT
+        /*
+         * If we've got too much on the deallocated list; free some
+         */
+        if(st_TotalDeallocated > FORTIFY_DEALLOCATED_MEMORY_LIMIT)
+        {
+             st_PurgeDeallocatedBlocks(st_TotalDeallocated - 
FORTIFY_DEALLOCATED_MEMORY_LIMIT, file, line);
+        }
+    #endif
+
+        /*
+         * End critical region
+         */
+        FORTIFY_UNLOCK();
+    }
+    else
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+    {
+               /*
+                * Free the User Label
+                */
+               if(h->Label)
+               {
+                       free(h->Label);
+               }                       
+
+#ifdef FORTIFY_FILL_ON_DEALLOCATE
+        /*
+         * Nuke out all memory that is about to be freed, including the header
+         */
+        st_SetFortification(ptr, FORTIFY_FILL_ON_DEALLOCATE_VALUE,
+                              FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size + FORTIFY_AFTER_SIZE);
+#endif /* FORTIFY_FILL_ON_DEALLOCATE */
+
+        /*
+         * And do the actual free
+         */
+        free(ptr);
+    }
+}
+
+
+/*
+ * Fortify_LabelPointer() - Labels the memory block
+ * with a string provided by the user. This function
+ * takes a copy of the passed in string.
+ * The pointer MUST be one returned by a Fortify
+ * allocation function.
+ */
+void
+Fortify_LabelPointer(void *uptr, const char *label, const char *file, unsigned 
long line)
+{
+       if(!st_Disabled)
+       {
+               unsigned char *ptr = (unsigned char *)uptr
+                              - FORTIFY_HEADER_SIZE - 
FORTIFY_ALIGNED_BEFORE_SIZE;
+               struct Header *h = (struct Header *)ptr;
+
+               /* make sure the pointer is okay */
+               Fortify_CheckPointer(uptr, file, line);
+       
+               /* free the previous label */
+               if(h->Label)
+               {
+                       free(h->Label);
+               }       
+       
+               /* make sure the label is sensible */
+               assert(label);
+
+               /* copy it in */
+               h->Label = (char*)malloc(strlen(label)+1);
+               strcpy(h->Label, label);
+               
+               /* update the checksum */
+               st_MakeHeaderValid(h);
+       }
+}
+
+/*
+ * Fortify_CheckPointer() - Returns true if the uptr
+ * points to a valid piece of Fortify_Allocated()'d
+ * memory. The memory must be on the allocated list,
+ * and it's fortifications must be intact.
+ * Always returns TRUE if Fortify is disabled.
+ */
+int FORTIFY_STORAGE
+Fortify_CheckPointer(void *uptr, const char *file, unsigned long line)
+{
+    unsigned char *ptr = (unsigned char *)uptr
+                              - FORTIFY_HEADER_SIZE - 
FORTIFY_ALIGNED_BEFORE_SIZE;
+    struct Header *h = (struct Header *)ptr;
+    int r;
+
+    if(st_Disabled)
+        return 1;
+
+    FORTIFY_LOCK();
+
+    if(!st_IsOnAllocatedList(h))
+    {
+#ifdef FORTIFY_NO_PERCENT_P
+        sprintf(st_Buffer, "\nFortify: Invalid pointer (0x%08lx) detected at 
%s.%lu\n",
+#else
+        sprintf(st_Buffer, "\nFortify: Invalid pointer (%p) detected at 
%s.%lu\n",
+#endif
+                                 uptr, file, line);
+        st_Output(st_Buffer);
+        FORTIFY_UNLOCK();
+        return(0);
+    }
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    if(st_IsOnDeallocatedList(h))
+    {
+#ifdef FORTIFY_NO_PERCENT_P
+        sprintf(st_Buffer, "\nFortify: Deallocated pointer (0x%08lx) detected 
at %s.%lu\n",
+#else
+        sprintf(st_Buffer, "\nFortify: Deallocated pointer (%p) detected at 
%s.%lu\n",
+#endif
+                           uptr, file, line);
+        st_Output(st_Buffer);
+        sprintf(st_Buffer, "         Memory block was deallocated by \"%s\" at 
%s.%lu\n",
+                           st_DeallocatorName[h->Deallocator], h->FreedFile, 
h->FreedLine);
+        st_Output(st_Buffer);
+        FORTIFY_UNLOCK();
+        return(0);
+    }
+#endif
+
+    r = st_CheckBlock(h, file, line);
+    FORTIFY_UNLOCK();
+    return r;
+}
+
+/*
+ * Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output) -
+ * Sets the function used to output all error and
+ * diagnostic messages. The output function  takes 
+ * a single const unsigned char * argument, and must be 
+ * able to handle newlines. This function returns the 
+ * old output function.
+ */
+Fortify_OutputFuncPtr FORTIFY_STORAGE
+Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output)
+{
+    Fortify_OutputFuncPtr Old = st_Output;
+
+    st_Output = Output;
+  
+    return(Old);
+}
+
+/*
+ * Fortify_SetAllocateFailRate(int Percent) - 
+ * Fortify_Allocate() will "fail" this Percent of 
+ * the time, even if the memory is available. 
+ * Useful to "stress-test" an application. 
+ * Returns the old value.
+ * The fail rate defaults to 0 (a good default I think).
+ */
+int FORTIFY_STORAGE
+Fortify_SetAllocateFailRate(int Percent)
+{
+    int Old = st_AllocateFailRate;
+  
+    st_AllocateFailRate = Percent;
+  
+    return(Old);
+}
+
+ 
+/*
+ * Fortify_CheckAllMemory() - Checks the fortifications
+ * of all memory on the allocated list. And, if 
+ * FORTIFY_DEALLOCATED_MEMORY is enabled, all the
+ * known deallocated memory as well.
+ * Returns the number of blocks that failed. 
+ * Always returns 0 if Fortify is disabled.
+ */
+unsigned long FORTIFY_STORAGE
+Fortify_CheckAllMemory(const char *file, unsigned long line)
+{
+    struct Header *curr = st_AllocatedHead;
+    unsigned long count = 0;
+
+    if(st_Disabled)
+        return 0;
+
+    FORTIFY_LOCK();
+
+    /*
+     * Check the allocated memory
+     */ 
+    while(curr)
+    {
+        if(!st_CheckBlock(curr, file, line))
+            count++;
+
+        curr = curr->Next;      
+    }
+
+    /*
+     * Check the deallocated memory while you're at it
+     */
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    curr = st_DeallocatedHead;
+    while(curr)
+    {
+        if(!st_CheckDeallocatedBlock(curr, file, line))
+            count++;
+
+        curr = curr->Next;      
+    }
+#endif    
+
+    /*  
+     * If we know where we are, and everything is cool,
+     * remember that. It might be important.
+     */
+    if(file && count == 0)
+    {
+        st_LastVerifiedFile = file;
+        st_LastVerifiedLine = line;
+    }
+
+    FORTIFY_UNLOCK();
+    return(count);
+}
+
+
+/*
+ * Fortify_EnterScope() - enters a new Fortify scope 
+ * level. Returns the new scope level.
+ */
+unsigned char FORTIFY_STORAGE
+Fortify_EnterScope(const char *file, unsigned long line)
+{
+    return(++st_Scope);
+}
+
+/* Fortify_LeaveScope - leaves a Fortify scope level,
+ * also prints a memory dump of all non-freed memory 
+ * that was allocated during the scope being exited.
+ * Does nothing and returns 0 if Fortify is disabled.
+ */
+unsigned char FORTIFY_STORAGE
+Fortify_LeaveScope(const char *file, unsigned long line)
+{
+    struct Header *curr = st_AllocatedHead;
+    unsigned long size = 0, count = 0;
+
+    if(st_Disabled)
+        return 0;
+
+    FORTIFY_LOCK();
+
+    st_Scope--;
+    while(curr)
+    {
+        if(curr->Scope > st_Scope)
+        {
+            if(count == 0)
+            {
+                sprintf(st_Buffer, "\nFortify: Memory leak detected leaving 
scope at %s.%lu\n", file, line);
+                st_Output(st_Buffer);
+                sprintf(st_Buffer, "%10s %8s %s\n", "Address", "Size", 
"Allocator");
+                st_Output(st_Buffer);
+            }
+            
+            st_OutputHeader(curr);
+            count++;
+            size += curr->Size;
+        }
+
+        curr = curr->Next;      
+    }
+
+    if(count)
+    {
+        sprintf(st_Buffer,"%10s %8lu bytes in %lu blocks with %lu bytes 
overhead\n", 
+                "total", size, count, count * FORTIFY_OVERHEAD);
+        st_Output(st_Buffer);
+    }
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    /* 
+     * Quietly free all the deallocated memory 
+     * that was allocated in this scope that 
+     * we are still tracking
+     */
+    st_PurgeDeallocatedScope( st_Scope, file, line );
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+    FORTIFY_UNLOCK();
+    return(st_Scope);
+}
+
+/*
+ * Fortify_ListAllMemory() - Outputs the entire 
+ * list of currently allocated memory. For each block 
+ * is output it's Address, Size, and the SourceFile and 
+ * Line that allocated it.
+ *
+ * If there is no memory on the list, this function 
+ * outputs nothing.
+ *
+ * It returns the number of blocks on the list, unless 
+ * Fortify has been disabled, in which case it always 
+ * returns 0.
+ */
+unsigned long FORTIFY_STORAGE
+Fortify_ListAllMemory(const char *file, unsigned long line)
+{
+    struct Header *curr = st_AllocatedHead;
+    unsigned long size = 0, count = 0;
+
+    if(st_Disabled)
+        return 0;
+
+    Fortify_CheckAllMemory(file, line);
+
+    FORTIFY_LOCK();
+
+    if(curr)
+    {
+        sprintf(st_Buffer, "\nFortify: Memory List at %s.%lu\n", file, line);
+        st_Output(st_Buffer);
+        sprintf(st_Buffer, "%10s %8s %s\n", "Address", "Size", "Allocator");
+        st_Output(st_Buffer);
+                                
+        while(curr)
+        {
+            st_OutputHeader(curr);
+            count++;
+            size += curr->Size;
+            curr = curr->Next;      
+        }
+                     
+        sprintf(st_Buffer, "%10s %8lu bytes in %lu blocks and %lu bytes 
overhead\n", 
+                           "total", size, count, count * FORTIFY_OVERHEAD);
+        st_Output(st_Buffer);
+    }
+  
+    FORTIFY_UNLOCK();
+    return(count);
+}
+
+/*
+ * Fortify_DumpAllMemory() - Outputs the entire list of 
+ * currently allocated memory. For each allocated block 
+ * is output it's Address, Size, the SourceFile and Line
+ * that allocated it, a hex dump of the contents of the 
+ * memory and an ascii dump of printable characters.
+ *
+ * If there is no memory on the list, this function outputs nothing.
+ */
+unsigned long FORTIFY_STORAGE
+Fortify_DumpAllMemory(const char *file, unsigned long line)
+{
+    struct Header *curr = st_AllocatedHead;
+    unsigned long count = 0;
+
+    if(st_Disabled)
+        return 0;
+
+    Fortify_CheckAllMemory(file, line);
+
+    FORTIFY_LOCK();
+
+    while(curr)
+    {
+        sprintf(st_Buffer, "\nFortify: Hex Dump of %s at %s.%lu\n",
+                st_MemoryBlockString(curr), file, line);
+        st_Output(st_Buffer);
+        st_OutputMemory(curr);
+        st_Output("\n");
+        count++;
+
+        curr = curr->Next;
+    }
+
+    FORTIFY_UNLOCK();
+    return(count);
+}
+
+/* Fortify_OutputStatistics() - displays statistics 
+ * about the maximum amount of memory that was 
+ * allocated at any one time.
+ */
+void FORTIFY_STORAGE
+Fortify_OutputStatistics(const char *file, unsigned long line)
+{
+    if(st_Disabled)
+        return;
+
+    sprintf(st_Buffer, "\nFortify: Statistics at %s.%lu\n", file, line);
+    st_Output(st_Buffer);
+
+    sprintf(st_Buffer, "         Memory currently allocated: %lu bytes in %lu 
blocks\n",
+                                 st_CurAllocation, st_CurBlocks);
+    st_Output(st_Buffer);
+    sprintf(st_Buffer, "         Maximum memory allocated at one time: %lu 
bytes in %lu blocks\n", 
+                                 st_MaxAllocation, st_MaxBlocks);
+    st_Output(st_Buffer);
+    sprintf(st_Buffer, "         There have been %lu allocations and %lu 
deallocations\n",
+                                 st_Allocations, st_Frees);
+    st_Output(st_Buffer);
+    sprintf(st_Buffer, "         There was a total of %lu bytes allocated\n",
+                                 st_TotalAllocation);
+    st_Output(st_Buffer);
+    
+    if(st_Allocations > 0)
+    {
+        sprintf(st_Buffer, "         The average allocation was %lu bytes\n",
+                                     st_TotalAllocation / st_Allocations);
+        st_Output(st_Buffer);                   
+    }    
+}
+
+/* Fortify_GetCurrentAllocation() - returns the number of
+ * bytes currently allocated.
+ */
+unsigned long FORTIFY_STORAGE
+Fortify_GetCurrentAllocation(const char *file, unsigned long line)
+{
+    if(st_Disabled)
+        return 0;
+
+    return st_CurAllocation;
+}
+
+/* Fortify_SetAllocationLimit() - set a limit on the total
+ * amount of memory allowed for this application.
+ */
+void FORTIFY_STORAGE
+Fortify_SetAllocationLimit(unsigned long NewLimit, const char *file, unsigned 
long line)
+{
+    st_AllocationLimit = NewLimit;
+}
+
+/*
+ * Fortify_Disable() - Run time method of disabling Fortify.
+ * Useful if you need to turn off Fortify without recompiling
+ * everything. Not as effective as compiling out, of course.
+ * The less memory allocated by Fortify when it is disabled
+ * the better.
+ * (Previous versions of Fortify did not allow it to be 
+ * disabled if there was any memory allocated at the time,
+ * but since in C++ memory is often allocated before main
+ * is even entered, this was useless so Fortify is now
+ * able to cope).
+ */
+void FORTIFY_STORAGE
+Fortify_Disable(const char *file, unsigned long line)
+{
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+    /* free all deallocated memory we might be tracking */
+    st_PurgeDeallocatedScope( 0, file, line );
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+    st_Disabled = 1;
+}
+
+
+
+/*
+ * st_CheckBlock - Check a block's header and fortifications.
+ * Returns true if the block is happy.
+ */
+static int
+st_CheckBlock(struct Header *h, const char *file, unsigned long line)
+{
+    unsigned char *ptr = (unsigned char *)h;
+    int result = 1;
+
+    if(!st_IsHeaderValid(h))
+    {
+        sprintf(st_Buffer,
+#ifdef FORTIFY_NO_PERCENT_P
+                "\nFortify: Invalid pointer (0x%08lx) or corrupted header 
detected at %s.%lu\n",
+#else
+                "\nFortify: Invalid pointer (%p) or corrupted header detected 
at %s.%lu\n",
+#endif
+                ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE, file, 
line);
+        st_Output(st_Buffer);
+        st_OutputLastVerifiedPoint();
+        return(0);
+    }
+
+    if(!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE,
+                           FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE))
+    {
+        sprintf(st_Buffer, "\nFortify: Underwrite detected before block %s at 
%s.%lu\n",
+                           st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+
+        st_OutputLastVerifiedPoint();
+        st_OutputFortification(ptr + FORTIFY_HEADER_SIZE,
+                            FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
+        result = 0;                        
+
+#ifdef FORTIFY_FILL_ON_CORRUPTION
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE, FORTIFY_BEFORE_VALUE, 
FORTIFY_ALIGNED_BEFORE_SIZE);
+#endif
+    }
+                           
+    if(!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                           FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))
+    {
+        sprintf(st_Buffer, "\nFortify: Overwrite detected after block %s at 
%s.%lu\n",
+                           st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+
+        st_OutputLastVerifiedPoint();
+        st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                            FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
+        result = 0;
+
+#ifdef FORTIFY_FILL_ON_CORRUPTION
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                         FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
+#endif
+    }
+ 
+    return(result);    
+}
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+
+/* 
+ * st_CheckDeallocatedBlock - Check a deallocated block's header and 
fortifications.
+ * Returns true if the block is happy.
+ */
+static int  
+st_CheckDeallocatedBlock(struct Header *h, const char *file, unsigned long 
line)
+{
+    unsigned char *ptr = (unsigned char *)h;
+    int result = 1;
+
+    if(!st_IsHeaderValid(h))
+    {
+        sprintf(st_Buffer,
+#ifdef FORTIFY_NO_PERCENT_P
+                "\nFortify: Invalid deallocated pointer (0x%08lx) or corrupted 
header detected at %s.%lu\n",
+#else
+                "\nFortify: Invalid deallocated pointer (%p) or corrupted 
header detected at %s.%lu\n",
+#endif
+                ptr + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE, file, 
line);
+        st_Output(st_Buffer);
+        st_OutputLastVerifiedPoint();
+        return(0);
+    }
+
+    if(!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE,
+                           FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE))
+    {
+        sprintf(st_Buffer, "\nFortify: Underwrite detected before deallocated 
block %s at %s.%lu\n",
+                           st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+        sprintf(st_Buffer, "         Memory block was deallocated by \"%s\" at 
%s.%lu\n",
+                           st_DeallocatorName[h->Deallocator], h->FreedFile, 
h->FreedLine);
+        st_Output(st_Buffer);
+
+        st_OutputLastVerifiedPoint();
+        st_OutputFortification(ptr + FORTIFY_HEADER_SIZE,
+                            FORTIFY_BEFORE_VALUE, FORTIFY_ALIGNED_BEFORE_SIZE);
+
+#ifdef FORTIFY_FILL_ON_CORRUPTION
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE, FORTIFY_BEFORE_VALUE, 
FORTIFY_ALIGNED_BEFORE_SIZE);
+#endif
+        result = 0;
+    }
+                           
+    if(!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                           FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE))
+    {
+        sprintf(st_Buffer, "\nFortify: Overwrite detected after deallocated 
block %s at %s.%lu\n",
+                           st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+        sprintf(st_Buffer, "         Memory block was deallocated by \"%s\" at 
%s.%lu\n",
+                           st_DeallocatorName[h->Deallocator], h->FreedFile, 
h->FreedLine);
+        st_Output(st_Buffer);
+
+        st_OutputLastVerifiedPoint();
+        st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                            FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
+
+#ifdef FORTIFY_FILL_ON_CORRUPTION
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE + h->Size,
+                         FORTIFY_AFTER_VALUE, FORTIFY_AFTER_SIZE);
+#endif
+        result = 0;
+    }
+
+#ifdef FORTIFY_FILL_ON_DEALLOCATE
+    if(!st_CheckFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                           FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size))
+    {
+        sprintf(st_Buffer, "\nFortify: Write to deallocated block %s detected 
at %s.%lu\n",
+                           st_MemoryBlockString(h), file, line);
+        st_Output(st_Buffer);
+
+        sprintf(st_Buffer, "         Memory block was deallocated by \"%s\" at 
%s.%lu\n",
+                           st_DeallocatorName[h->Deallocator], h->FreedFile, 
h->FreedLine);
+        st_Output(st_Buffer);
+        st_OutputLastVerifiedPoint();
+    
+        st_OutputFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                            FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size);
+
+#ifdef FORTIFY_FILL_ON_CORRUPTION
+        st_SetFortification(ptr + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                            FORTIFY_FILL_ON_DEALLOCATE_VALUE, h->Size);
+#endif /* FORTIFY_FILL_ON_CORRUPTION */
+        result = 0;
+    }
+#endif /* FORTIFY_FILL_ON_DEALLOCATE */
+    return result;
+ }
+
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+
+/*
+ * st_CheckFortification - Checks if the _size_ 
+ * bytes from _ptr_ are all set to _value_
+ * Returns true if all is happy.
+ */
+static int 
+st_CheckFortification(unsigned char *ptr, unsigned char value, size_t size)
+{
+    while(size--)
+        if(*ptr++ != value)
+            return(0);
+      
+    return(1);      
+}
+
+/*
+ * st_SetFortification - Set the _size_ bytes from _ptr_ to _value_.
+ */
+static void 
+st_SetFortification(unsigned char *ptr, unsigned char value, size_t size)
+{
+    memset(ptr, value, size);
+}
+
+/*
+ * st_OutputFortification - Output the corrupted section of the fortification 
+ */
+static void
+st_OutputFortification(unsigned char *ptr, unsigned char value, size_t size)
+{
+    size_t offset, skipped, advance;
+    offset = 0;
+
+    sprintf(st_Buffer, "   Address   Offset Data (%02x)", value);
+    st_Output(st_Buffer);
+
+    while(offset < size)
+    {
+        /* 
+         * Skip 3 or more 'correct' lines
+         */
+        if((size - offset) < 3 * 16)             
+            advance = size - offset;
+        else
+            advance = 3 * 16;
+        if(advance > 0 && st_CheckFortification(ptr+offset, value, advance))
+        {
+            offset += advance;
+            skipped = advance;
+                 
+            if(size - offset < 16)             
+                advance = size - offset;
+            else
+                advance = 16;
+             
+            while(advance > 0 && st_CheckFortification(ptr+offset, value, 
advance))
+            {
+                offset  += advance;
+                skipped += advance;
+                if(size - offset < 16)             
+                    advance = size - offset;
+                else
+                    advance = 16;
+            }    
+            sprintf(st_Buffer, "\n                        ...%lu bytes 
skipped...", (unsigned long)skipped);
+            st_Output(st_Buffer);
+            continue;
+        }
+        else
+        {
+            if(size - offset < 16)
+                st_HexDump(ptr, offset, size-offset, 0);
+            else
+                st_HexDump(ptr, offset, 16, 0);
+                
+            offset += 16;
+        }
+    }
+
+    st_Output("\n");
+}
+
+/*
+ * st_HexDump - output a nice hex dump of "size" bytes, starting at "ptr" + 
"offset"
+ */
+static void
+st_HexDump(unsigned char *ptr, size_t offset, size_t size, int title)
+{
+    char ascii[17];
+    int  column;
+    int  output;
+
+    if(title)
+        st_Output("   Address   Offset Data");
+
+    column = 0;
+    ptr += offset;
+    output = 0;
+
+    while(output < size)
+    {
+        if(column == 0)
+        {
+#ifdef FORTIFY_NO_PERCENT_P
+            sprintf(st_Buffer, "\n0x%08lx %8lu ", ptr, (unsigned long)offset);
+#else
+            sprintf(st_Buffer, "\n%10p %8lu ", ptr, (unsigned long)offset);
+#endif
+            st_Output(st_Buffer);
+        }
+
+        sprintf(st_Buffer, "%02x%s", *ptr, ((column % 4) == 3) ? " " : "");
+        st_Output(st_Buffer);
+
+        ascii[ column ] = isprint( *ptr ) ? (char)(*ptr) : (char)('.');
+        ascii[ column + 1 ] = '\0';
+
+        ptr++;
+        offset++;
+        output++;
+        column++;
+
+        if(column == 16)
+        {
+            st_Output( "   \"" );
+            st_Output( ascii );
+            st_Output( "\"" );
+            column = 0;
+        }
+    }
+
+    if ( column != 0 )
+    {
+        while ( column < 16 )
+        {
+            if( column % 4 == 3 )
+                st_Output( "   " );
+            else
+                st_Output( "  " );
+
+            column++;
+        }
+        st_Output( "   \"" );
+        st_Output( ascii );
+        st_Output( "\"" );
+    }
+}
+
+/*
+ * st_IsHeaderValid - Returns true if the 
+ * supplied pointer does indeed point to a 
+ * real Header
+ */
+static int 
+st_IsHeaderValid(struct Header *h)                                
+{
+    return(st_ChecksumHeader(h) == FORTIFY_CHECKSUM_VALUE);
+}
+
+/*
+ * st_MakeHeaderValid - Updates the checksum 
+ * to make the header valid
+ */
+static void 
+st_MakeHeaderValid(struct Header *h)
+{
+    h->Checksum = 0;
+    h->Checksum = (unsigned short)(FORTIFY_CHECKSUM_VALUE - 
st_ChecksumHeader(h));
+}
+
+/*
+ * st_ChecksumHeader - Calculate (and return) 
+ * the checksum of the header. (Including the 
+ * Checksum field itself. If all is well, the 
+ * checksum returned by this function should
+ * be FORTIFY_CHECKSUM_VALUE
+ */
+static unsigned short
+st_ChecksumHeader(struct Header *h)
+{
+    unsigned short c, checksum, *p;
+  
+    for(c = 0, checksum = 0, p = (unsigned short *)h; 
+        c < FORTIFY_HEADER_SIZE/sizeof(unsigned short); c++)
+    {    
+        checksum += *p++;  
+    }    
+    
+    return(checksum);
+}                  
+
+/* 
+ * st_IsOnAllocatedList - Examines the allocated 
+ * list to see if the given header is on it.
+ */  
+static int 
+st_IsOnAllocatedList(struct Header *h)
+{
+    struct Header *curr;
+  
+    curr = st_AllocatedHead;
+    while(curr)
+    {
+        if(curr == h)
+            return(1);
+      
+        curr = curr->Next;
+    }
+  
+    return(0);
+}
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+/* 
+ * st_IsOnDeallocatedList - Examines the deallocated 
+ * list to see if the given header is on it.
+ */  
+static int 
+st_IsOnDeallocatedList(struct Header *h)
+{
+    struct Header *curr;
+  
+    curr = st_DeallocatedHead;
+    while(curr)
+    {
+        if(curr == h)
+            return(1);
+      
+        curr = curr->Next;
+    }
+  
+    return(0);
+}
+
+/*
+ * st_PurgeDeallocatedBlocks - free at least "Bytes"
+ * worth of deallocated memory, starting at the 
+ * oldest deallocated block.
+ * Returns true if any blocks were freed.
+ */
+static int
+st_PurgeDeallocatedBlocks(unsigned long Bytes, const char *file, unsigned long 
line)
+{
+    unsigned long FreedBytes = 0;
+    unsigned long FreedBlocks = 0;
+
+#ifdef FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+    sprintf(st_Buffer, "\nFortify: Warning - Discarding deallocated memory at 
%s.%lu\n", 
+                       file, line);
+    st_Output(st_Buffer);
+#endif /* FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+
+    while(st_DeallocatedTail && FreedBytes < Bytes)
+    {
+        st_CheckDeallocatedBlock(st_DeallocatedTail, file, line);
+        FreedBytes += st_DeallocatedTail->Size;
+        FreedBlocks++;
+#ifdef FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+#ifdef FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+        sprintf(st_Buffer, "                %s\n",
+                           
st_DeallocatedMemoryBlockString(st_DeallocatedTail));
+        st_Output(st_Buffer);
+#endif /* FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+#endif /* FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+        st_FreeDeallocatedBlock(st_DeallocatedTail, file, line);
+    }
+
+    return FreedBlocks != 0;
+}
+
+/*
+ * st_PurgeDeallocatedScope - free all deallocated
+ * memory blocks that were allocated within "Scope"
+ */
+static int
+st_PurgeDeallocatedScope(unsigned char Scope, const char *file, unsigned long 
line)
+{
+    struct Header *curr, *next;
+    unsigned long FreedBlocks = 0;
+
+    curr = st_DeallocatedHead;
+    while(curr)
+    {
+        next = curr->Next;
+        if(curr->Scope >= Scope)
+        {
+            st_FreeDeallocatedBlock(curr, file, line);
+            FreedBlocks++;
+        }
+
+        curr = next;
+    }
+    
+    return FreedBlocks != 0;
+}
+
+/*
+ * st_FreeDeallocatedBlock - actually remove
+ * a deallocated block from the deallocated 
+ * list, and actually free it's memory.
+ */
+static void
+st_FreeDeallocatedBlock(struct Header *h, const char *file, unsigned long line)
+{
+    st_CheckDeallocatedBlock( h, file, line );
+
+   /* 
+    * Begin Critical region 
+    */
+    FORTIFY_LOCK();
+
+    st_TotalDeallocated -= h->Size;
+    
+    if(st_DeallocatedHead == h)
+    {
+        st_DeallocatedHead = h->Next;
+    }
+    
+    if(st_DeallocatedTail == h)
+    {
+        st_DeallocatedTail = h->Prev;
+    }
+    
+    if(h->Prev)
+    {
+        st_CheckDeallocatedBlock(h->Prev, file, line);
+        h->Prev->Next = h->Next;
+        st_MakeHeaderValid(h->Prev);    
+    }
+    
+    if(h->Next)
+    {
+        st_CheckDeallocatedBlock(h->Next, file, line);
+        h->Next->Prev = h->Prev;
+        st_MakeHeaderValid(h->Next);    
+    }
+
+       /*
+        * Free the label
+        */
+       if(h->Label) 
+       {
+               free(h->Label);
+       }
+
+    /*
+     * Nuke out all memory that is about to be freed, including the header
+     */
+    st_SetFortification((unsigned char*)h, FORTIFY_FILL_ON_DEALLOCATE_VALUE,
+                        FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE + 
h->Size + FORTIFY_AFTER_SIZE);
+
+    /*
+     * And do the actual free
+     */
+    free(h);
+    
+    /*
+     * End critical region
+     */
+    FORTIFY_UNLOCK();    
+}
+
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+/*
+ * st_OutputMemory - Hex and ascii dump the 
+ * user memory of a block.
+ */
+static void
+st_OutputMemory(struct Header *h)
+{
+    st_HexDump((unsigned char*)h + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+               0, h->Size, 1);
+}
+
+
+/*
+ * st_OutputHeader - Output the header
+ */
+static void 
+st_OutputHeader(struct Header *h)
+{
+       if(h->Label == NULL)
+       {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_Buffer, "0x%08lx %8lu %s.%lu\n", 
+#else
+           sprintf(st_Buffer, "%10p %8lu %s.%lu\n", 
+#endif
+                              (unsigned char*)h + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                          (unsigned long)h->Size,
+                              h->File, h->Line);
+    }                   
+    else
+    {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_Buffer, "0x%08lx %8lu %s.%lu %s\n", 
+#else
+           sprintf(st_Buffer, "%10p %8lu %s.%lu %s\n", 
+#endif
+                          (unsigned char*)h + FORTIFY_HEADER_SIZE + 
FORTIFY_ALIGNED_BEFORE_SIZE,
+                              (unsigned long)h->Size,
+                          h->File, h->Line, h->Label);
+    }
+    st_Output(st_Buffer);
+}
+
+/*
+ * st_OutputLastVerifiedPoint - output the last
+ * known point where everything was hoopy.
+ */
+static void 
+st_OutputLastVerifiedPoint()
+{
+    sprintf(st_Buffer, "         Memory integrity was last verified at 
%s.%lu\n", 
+                       st_LastVerifiedFile,
+                       st_LastVerifiedLine);
+    st_Output(st_Buffer);
+}
+
+/*
+ * st_MemoryBlockString - constructs a string that 
+ * desribes a memory block. (pointer,size,allocator,label)
+ */
+static const char *
+st_MemoryBlockString(struct Header *h)
+{
+    static char st_BlockString[512];
+    
+    if(h->Label == 0)
+    {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_BlockString,"(0x%08lx,%lu,%s.%lu)",
+#else
+           sprintf(st_BlockString,"(%p,%lu,%s.%lu)",
+#endif
+               (char*)h + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
+                   (unsigned long)h->Size, h->File, h->Line);
+       }            
+       else
+       {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_BlockString,"(0x%08lx,%lu,%s.%lu,%s)",
+#else
+           sprintf(st_BlockString,"(%p,%lu,%s.%lu,%s)",
+#endif
+               (char*)h + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
+                   (unsigned long)h->Size, h->File, h->Line, h->Label);
+       }
+
+    return st_BlockString;
+}
+
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+#ifdef FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+#ifdef FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY
+/*
+ * st_DeallocatedMemoryBlockString - constructs
+ * a string that desribes a deallocated memory
+ * block. (pointer,size,allocator,deallocator)
+ */
+
+static const char *
+st_DeallocatedMemoryBlockString(struct Header *h)
+{
+    static char st_BlockString[256];
+
+       if(h->Label == 0)
+       {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_BlockString,"(0x%08lx,%lu,%s.%lu,%s.%lu)",
+#else
+           sprintf(st_BlockString,"(%p,%lu,%s.%lu,%s.%lu)",
+#endif
+               (char*)h + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
+                   (unsigned long)h->Size, h->File, h->Line, h->FreedFile, 
h->FreedLine);
+       }            
+       else
+       {
+#ifdef FORTIFY_NO_PERCENT_P
+           sprintf(st_BlockString,"(0x%08lx,%lu,%s.%lu,%s.%lu,%s)",
+#else
+           sprintf(st_BlockString,"(%p,%lu,%s.%lu,%s.%lu,%s)",
+#endif
+               (char*)h + FORTIFY_HEADER_SIZE + FORTIFY_ALIGNED_BEFORE_SIZE,
+                   (unsigned long)h->Size, h->File, h->Line, h->FreedFile, 
h->FreedLine, h->Label);
+       }
+
+    return st_BlockString;
+}
+#endif /* FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+#endif /* FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+#endif /* FORTIFY_TRACK_DEALLOCATED_MEMORY */
+
+
+/*
+ * st_DefaultOutput - the default output function
+ */
+static void
+st_DefaultOutput(const char *String)
+{
+    fprintf(stdout, String);
+    fflush(stdout);
+}
+
+/*
+ * Fortify_malloc - Fortify's replacement malloc()
+ */
+void *FORTIFY_STORAGE
+Fortify_malloc(size_t size, const char *file, unsigned long line)
+{
+    return Fortify_Allocate(size, Fortify_Allocator_malloc, file, line);
+}
+
+/*
+ * Fortify_realloc - Fortify's replacement realloc()
+ */
+void *
+Fortify_realloc(void *uptr, size_t new_size, const char *file, unsigned long 
line)
+{
+    unsigned char *ptr = (unsigned char *)uptr - FORTIFY_HEADER_SIZE - 
FORTIFY_ALIGNED_BEFORE_SIZE;
+    struct Header *h = (struct Header *)ptr;
+    void *new_ptr;
+
+    /*
+     * If Fortify is disabled, we gotta do this a little 
+     * differently.
+     */
+    if(!st_Disabled) 
+    {
+        if(!uptr)
+            return(Fortify_Allocate(new_size, Fortify_Allocator_realloc, file, 
line));
+        
+        if(!st_IsOnAllocatedList(h))
+        {
+#ifdef FORTIFY_TRACK_DEALLOCATED_MEMORY
+            if(st_IsOnDeallocatedList(h))
+            {
+                sprintf(st_Buffer, "\nFortify: Deallocated memory block passed 
to \"%s\" at %s.%lu\n",
+                                    
st_AllocatorName[Fortify_Allocator_realloc], file, line);
+                st_Output(st_Buffer);
+                sprintf(st_Buffer,   "         Memory block %s was deallocated 
by \"%s\" at %s.%lu\n",
+                                   st_MemoryBlockString(h),
+                                   st_DeallocatorName[h->Deallocator], 
h->FreedFile, h->FreedLine);
+                st_Output(st_Buffer);
+                return 0;
+            }
+#endif
+
+            sprintf(st_Buffer, 
+#ifdef FORTIFY_NO_PERCENT_P
+                    "\nFortify: Invalid pointer (0x%08lx) passed to realloc at 
%s.%lu\n",
+#else
+                    "\nFortify: Invalid pointer (%p) passed to realloc at 
%s.%lu\n",
+#endif            
+                    ptr, file, line);
+            st_Output(st_Buffer);
+            return 0;
+        }
+
+        if(!st_CheckBlock(h, file, line))
+            return 0;
+      
+        new_ptr = Fortify_Allocate(new_size, Fortify_Allocator_realloc, file, 
line);
+        if(!new_ptr)
+        {
+            return(0);
+        }
+      
+        if(h->Size < new_size) 
+            memcpy(new_ptr, uptr, h->Size);
+        else
+            memcpy(new_ptr, uptr, new_size);
+    
+        Fortify_Deallocate(uptr, Fortify_Deallocator_realloc, file, line);
+        return(new_ptr);
+    }
+    else
+    {
+        /*
+         * If the old block was fortified, we can't use normal realloc.
+         */
+        if(st_IsOnAllocatedList(h))
+        {
+            new_ptr = Fortify_Allocate(new_size, Fortify_Allocator_realloc, 
file, line);
+            if(!new_ptr)
+                return(0);
+          
+            if(h->Size < new_size) 
+                memcpy(new_ptr, uptr, h->Size);
+            else
+                memcpy(new_ptr, uptr, new_size);
+        
+            Fortify_Deallocate(uptr, Fortify_Deallocator_realloc, file, line);
+            return(new_ptr);
+        }
+        else /* easy */
+        {
+            return realloc(uptr, new_size);
+        }
+    }
+}
+
+/*
+ * Fortify_calloc - Fortify's replacement calloc
+ */
+void *
+Fortify_calloc(size_t num, size_t size, const char *file, unsigned long line)
+{
+    if(!st_Disabled)
+    {
+        void *ptr = Fortify_Allocate(size * num, Fortify_Allocator_calloc, 
file, line);
+        if(ptr)
+        {
+            memset(ptr, 0, size*num);
+        }
+        return ptr;
+    }    
+    else
+    {
+        return calloc(num, size);
+    }
+}
+
+/*
+ * Fortify_free - Fortify's replacement free
+ */
+void  
+Fortify_free(void *uptr, const char *file, unsigned long line)
+{
+       /* it is defined to be safe to free(0) */
+       if(uptr == 0)
+        return;
+
+    Fortify_Deallocate(uptr, Fortify_Deallocator_free, file, line);
+}
+
+/*
+ * Fortify_strdup - Fortify's replacement strdup. Since strdup isn't
+ * ANSI, it is only provided if FORTIFY_STRDUP is defined.
+ */
+#ifdef FORTIFY_STRDUP
+char *FORTIFY_STORAGE
+Fortify_strdup(const char *oldStr, const char *file, unsigned long line)
+{
+    if(!st_Disabled)
+    {
+        char *newStr = Fortify_Allocate(strlen(oldStr)+1, 
Fortify_Allocator_strdup, file, line);
+        if(newStr)
+        {
+            strcpy(newStr, oldStr);
+        }
+    
+        return newStr;
+    }    
+    else
+    {
+        return strdup(oldStr);
+    }
+}
+#endif /* FORTIFY_STRDUP */
+
+static void
+st_OutputDeleteTrace()
+{
+#ifdef __cplusplus
+    if(st_DeleteStackTop > 1)
+    {
+        sprintf(st_Buffer, "Delete Trace: %s.%lu\n", 
st_DeleteFile[st_DeleteStackTop-1],
+                                                     
st_DeleteLine[st_DeleteStackTop-1]);
+        st_Output(st_Buffer);
+        for(int c = st_DeleteStackTop-2; c >= 0; c--)
+        {
+            sprintf(st_Buffer, "              %s.%lu\n", st_DeleteFile[c],
+                                                         st_DeleteLine[c]);
+            st_Output(st_Buffer);
+        }
+    }
+#endif
+}
+
+#ifdef __cplusplus
+
+/*
+ * st_NewHandler() - there is no easy way to get
+ * the new handler function. And isn't it great
+ * how the new handler doesn't take a parameter
+ * giving the size of the request that failed.
+ * Thanks Bjarne!
+ */
+Fortify_NewHandlerFunc
+st_NewHandler()
+{
+    /* get the current handler */
+    Fortify_NewHandlerFunc handler = set_new_handler(0);
+
+    /* and set it back (since we cant 
+     * get it without changing it)
+     */
+    set_new_handler(handler);
+    
+    return handler;
+}
+
+/*
+ * operator new - Fortify's replacement new, 
+ * without source-code information.
+ */
+void *FORTIFY_STORAGE
+operator new(size_t size)
+{
+    void *p;
+    
+    while((p = Fortify_Allocate(size, Fortify_Allocator_new, 
+                                st_AllocatorName[Fortify_Allocator_new], 0)) 
== 0)
+    {                            
+        if(st_NewHandler())
+            (*st_NewHandler())();
+        else
+            return 0;
+    }
+
+    return p;
+}
+
+/*
+ * operator new - Fortify's replacement new,
+ * with source-code information
+ */
+void *FORTIFY_STORAGE
+operator new(size_t size, const char *file, unsigned long line)
+{
+    void *p;
+
+    while((p = Fortify_Allocate(size, Fortify_Allocator_new, file, line)) == 0)
+    {
+        if(st_NewHandler())
+            (*st_NewHandler())();
+        else
+            return 0;
+    }
+    
+    return p;
+}
+
+#ifdef FORTIFY_PROVIDE_ARRAY_NEW
+
+/*
+ * operator new[], without source-code info
+ */
+void *FORTIFY_STORAGE
+operator new[](size_t size) 
+{
+    void *p;
+
+    while((p = Fortify_Allocate(size, Fortify_Allocator_array_new,
+                                st_AllocatorName[Fortify_Allocator_array_new], 
0)) == 0)
+    {                                
+        if(st_NewHandler())
+            (*st_NewHandler())();    
+        else    
+            return 0;
+    }
+    
+    return p;
+}
+
+/*
+ * operator new[], with source-code info
+ */
+void *FORTIFY_STORAGE
+operator new[](size_t size, const char *file, unsigned long line)
+{
+    void *p;
+
+    while((p = Fortify_Allocate(size, Fortify_Allocator_array_new, file, 
line)) == 0)
+    {
+        if(st_NewHandler())
+            (*st_NewHandler())(); 
+        else
+            return 0;
+    }
+
+    return p;
+}
+
+#endif /* FORTIFY_PROVIDE_ARRAY_NEW */
+
+/*
+ * Fortify_PreDelete - C++ does not allow overloading
+ * of delete, so the delete macro calls Fortify_PreDelete
+ * with the source-code info, and then calls delete.
+ */
+void FORTIFY_STORAGE
+Fortify_PreDelete(const char *file, unsigned long line)
+{
+    FORTIFY_LOCK();
+
+    /*
+     * Push the source code info for the delete onto the delete stack
+     * (if we have enough room, of course)
+     */
+    if(st_DeleteStackTop < FORTIFY_DELETE_STACK_SIZE)
+    {
+        st_DeleteFile[st_DeleteStackTop] = file;
+        st_DeleteLine[st_DeleteStackTop] = line;
+    }
+
+    st_DeleteStackTop++;
+}
+
+/*
+ * Fortify_PostDelete() - Pop the delete source-code info
+ * off the source stack.
+ */
+void FORTIFY_STORAGE
+Fortify_PostDelete()
+{
+    st_DeleteStackTop--;
+
+    FORTIFY_UNLOCK();
+}
+
+/*
+ * operator delete - fortify's replacement delete
+ */
+void FORTIFY_STORAGE
+operator delete(void *uptr)
+{
+    const char *file;
+    unsigned long line;
+
+     /*
+      * It is defined to be harmless to delete 0
+      */
+    if(uptr == 0)
+        return;
+
+    /*
+     * find the source-code info
+     */
+    if(st_DeleteStackTop)
+    {
+        if(st_DeleteStackTop < FORTIFY_DELETE_STACK_SIZE)
+        {
+            file = st_DeleteFile[st_DeleteStackTop-1];
+            line = st_DeleteLine[st_DeleteStackTop-1];
+        }
+        else
+        {
+            file = st_DeleteFile[FORTIFY_DELETE_STACK_SIZE-1];
+            line = st_DeleteLine[FORTIFY_DELETE_STACK_SIZE-1];
+        }
+    }
+    else
+    {
+        file = st_DeallocatorName[Fortify_Deallocator_delete];
+        line = 0;
+    }
+
+    Fortify_Deallocate(uptr, Fortify_Deallocator_delete, file, line);
+}
+
+#ifdef FORTIFY_PROVIDE_ARRAY_DELETE
+
+/*
+ * operator delete[] - fortify's replacement delete[]
+ */
+void FORTIFY_STORAGE
+operator delete[](void *uptr)
+{
+    const char *file;
+    unsigned long line;
+
+     /*
+      * It is defined to be harmless to delete 0
+      */
+    if(uptr == 0)
+        return;
+
+    /*
+     * find the source-code info
+     */
+    if(st_DeleteStackTop)
+    {
+        if(st_DeleteStackTop < FORTIFY_DELETE_STACK_SIZE)
+        {
+            file = st_DeleteFile[st_DeleteStackTop-1];
+            line = st_DeleteLine[st_DeleteStackTop-1];
+        }
+        else
+        {
+            file = st_DeleteFile[FORTIFY_DELETE_STACK_SIZE-1];
+            line = st_DeleteLine[FORTIFY_DELETE_STACK_SIZE-1];
+        }
+    }
+    else
+    {
+        file = st_DeallocatorName[Fortify_Deallocator_array_delete];
+        line = 0;
+    }
+
+    Fortify_Deallocate(uptr, Fortify_Deallocator_array_delete, file, line);
+}
+
+#endif /* FORTIFY_PROVIDE_ARRAY_DELETE */
+
+#ifdef FORTIFY_AUTOMATIC_LOG_FILE
+/* Automatic log file stuff!
+ *
+ * AutoLogFile class. There can only ever be ONE of these
+ * instantiated! It is a static class, which means that
+ * it's constructor will be called at program initialization,
+ * and it's destructor will be called at program termination.
+ * We don't know if the other static class objects have been
+ * constructed/destructed yet, but this pretty much the best
+ * we can do with standard C++ language features.
+ */
+class Fortify_AutoLogFile
+{
+    static FILE *fp;
+    static int   written_something;
+    static char *init_string, *term_string;
+
+public:
+    Fortify_AutoLogFile()
+    {
+        written_something = 0;
+        Fortify_SetOutputFunc(Fortify_AutoLogFile::Output);
+        Fortify_EnterScope(init_string, 0);
+    }
+
+    static void Output(const char *s)
+    {
+        if(written_something == 0)
+        {
+            FORTIFY_FIRST_ERROR_FUNCTION;
+            fp = fopen(FORTIFY_LOG_FILENAME, "w");
+            if(fp)
+            {
+                time_t t;
+                time(&t);
+                fprintf(fp, "Fortify log started at %s\n", ctime(&t));
+                written_something = 1;
+            }    
+        }
+
+        if(fp)
+        {
+            fputs(s, fp);
+            fflush(fp);
+        }    
+    }
+    
+    ~Fortify_AutoLogFile()
+    {
+        Fortify_LeaveScope(term_string, 0);
+        Fortify_CheckAllMemory(term_string, 0);
+        if(fp)
+        {
+            time_t t;
+            time(&t);
+            fprintf(fp, "\nFortify log closed at %s\n", ctime(&t));
+            fclose(fp);
+            fp = 0;
+        }    
+    }
+};
+
+FILE *Fortify_AutoLogFile::fp = 0;
+int   Fortify_AutoLogFile::written_something = 0;
+char *Fortify_AutoLogFile::init_string = "Program Initialization";
+char *Fortify_AutoLogFile::term_string = "Program Termination";
+
+static Fortify_AutoLogFile Abracadabra;
+
+#endif /* FORTIFY_AUTOMATIC_LOG_FILE */
+
+#endif /* __cplusplus */
+
+#endif /* FORTIFY */
diff --git a/frontends/amiga/fortify/fortify.h 
b/frontends/amiga/fortify/fortify.h
new file mode 100755
index 0000000..3dabff1
--- /dev/null
+++ b/frontends/amiga/fortify/fortify.h
@@ -0,0 +1,273 @@
+/* fortify.h - V2.2 - All C & C++ source files to be fortified should #include 
this file */
+
+/*
+ *     This  software  is  not public domain.  All material in
+ * this  archive  is (C) Copyright 1995 Simon P.  Bullen.  The
+ * software  is  freely distributable, with the condition that
+ * no   more   than  a  nominal  fee  is  charged  for  media.
+ * Everything  in  this distribution must be kept together, in
+ * original, unmodified form.
+ *     The software may be modified for your own personal use,
+ * but modified files may not be distributed.
+ *     The  material  is  provided "as is" without warranty of
+ * any  kind.  The author accepts no responsibility for damage
+ * caused by this software.
+ *     This  software  may not be used in any way by Microsoft
+ * Corporation  or  its  subsidiaries, or current employees of
+ * Microsoft Corporation or its subsidiaries.
+ *     This  software  may  not  be used for the construction,
+ * development,  production,  or  testing of weapon systems of
+ * any kind.
+ *     This  software  may  not  be used for the construction,
+ * development,  production,  or  use  of plants/installations
+ * which  include  the  processing  of radioactive/fissionable
+ * material.
+ */
+
+/*  
+ *     If  you use this software at all, I'd love to hear from
+ * you.   All  questions,  criticisms, suggestions, praise and
+ * postcards are most welcome.
+ * 
+ *            email:    [email protected]
+ * 
+ *            snail:    Simon P. Bullen
+ *                      PO BOX 12138
+ *                      A'Beckett St.
+ *                      Melbourne 3000
+ *                      Australia
+ */
+
+#ifndef __FORTIFY_H__
+#define __FORTIFY_H__
+
+#include <stdlib.h>
+#include <string.h>
+
+/* the user's options */
+#include "ufortify.h"
+
+/* Ensure the configuration parameters have sensible defaults */
+#ifndef FORTIFY_STORAGE
+    #define FORTIFY_STORAGE
+#endif
+
+#ifndef FORTIFY_ALIGNMENT
+    #define FORTIFY_ALIGNMENT                    sizeof(double)
+#endif
+
+#ifndef FORTIFY_BEFORE_SIZE
+    #define FORTIFY_BEFORE_SIZE                  32
+#endif
+#ifndef FORTIFY_BEFORE_VALUE
+    #define FORTIFY_BEFORE_VALUE                 0xA3
+#endif
+
+#ifndef FORTIFY_AFTER_SIZE
+    #define FORTIFY_AFTER_SIZE                   32
+#endif
+
+#ifndef FORTIFY_AFTER_VALUE
+    #define FORTIFY_AFTER_VALUE                  0xA5
+#endif
+
+#ifndef FORTIFY_FILL_ON_ALLOCATE_VALUE    
+    #define FORTIFY_FILL_ON_ALLOCATE_VALUE       0xA7
+#endif
+
+#ifndef FORTIFY_FILL_ON_DEALLOCATE_VALUE
+    #define FORTIFY_FILL_ON_DEALLOCATE_VALUE     0xA9
+#endif
+
+#ifndef FORTIFY_LOCK
+    #define FORTIFY_LOCK()   
+#endif
+
+#ifndef FORTIFY_UNLOCK
+    #define FORTIFY_UNLOCK()  
+#endif
+
+#ifndef FORTIFY_CHECKSUM_VALUE
+    #define FORTIFY_CHECKSUM_VALUE               0x0AD0
+#endif
+
+#ifndef FORTIFY_DELETE_STACK_SIZE
+    #define FORTIFY_DELETE_STACK_SIZE    256
+#endif
+
+#ifndef FORTIFY_NEW_HANDLER_FUNC
+    typedef void (*Fortify_NewHandlerFunc)(void);
+    #define FORTIFY_NEW_HANDLER_FUNC Fortify_NewHandlerFunc
+#endif
+
+/*
+ * Code to detect and configure for various compilers lives here.
+ */
+
+#ifdef __GNUG__ 
+    /* GCC configuration */
+    #define FORTIFY_PROVIDE_ARRAY_NEW
+    #define FORTIFY_PROVIDE_ARRAY_DELETE
+#endif
+
+#ifdef __BC45__
+    /* Borland C++ 4.5 configuration */
+    #define FORTIFY_PROVIDE_ARRAY_NEW
+    #define FORTIFY_PROVIDE_ARRAY_DELETE
+    #define FORTIFY_FAIL_ON_ZERO_MALLOC
+#endif
+
+#ifdef __SASC
+       /* SAS configuration */
+       #define FORTIFY_FAIL_ON_ZERO_MALLOC
+#endif
+
+/* Allocators */
+#define Fortify_Allocator_malloc            0    /* ANSI C   */
+#define Fortify_Allocator_calloc            1    /* ANSI C   */
+#define Fortify_Allocator_realloc           2    /* ANSI C   */
+#define Fortify_Allocator_strdup            3    /*      C   */
+#define Fortify_Allocator_new               4    /* ANSI C++ */
+#define Fortify_Allocator_array_new         5    /* Some C++ */
+
+/* Deallocators */
+#define Fortify_Deallocator_nobody          0
+#define Fortify_Deallocator_free            1    /* ANSI C   */
+#define Fortify_Deallocator_realloc         2    /* ANSI C   */
+#define Fortify_Deallocator_delete          3    /* ANSI C++ */
+#define Fortify_Deallocator_array_delete    4    /* Some C++ */
+
+/* Public Fortify Types */
+typedef void (*Fortify_OutputFuncPtr)(const char *);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Core Fortify Functions */
+void *Fortify_Allocate  (size_t size, unsigned char allocator, const char 
*file, unsigned long line);
+void  Fortify_Deallocate(void *uptr,  unsigned char deallocator, const char 
*file, unsigned long line);
+unsigned long Fortify_CheckAllMemory(const char *file, unsigned long line);
+unsigned long Fortify_ListAllMemory (const char *file, unsigned long line);
+unsigned long Fortify_DumpAllMemory (const char *file, unsigned long line);
+int   Fortify_CheckPointer(void *uptr, const char *file, unsigned long line);
+void  Fortify_LabelPointer(void *uptr, const char *label, const char *file, 
unsigned long line);
+unsigned char Fortify_EnterScope(const char *file, unsigned long line);
+unsigned char Fortify_LeaveScope(const char *file, unsigned long line);
+void  Fortify_OutputStatistics(const char *file, unsigned long line);
+unsigned long Fortify_GetCurrentAllocation(const char *file, unsigned long 
line);
+void  Fortify_SetAllocationLimit(unsigned long Limit, const char *file, 
unsigned long line);
+int   Fortify_SetFailRate(int Percent);
+Fortify_OutputFuncPtr Fortify_SetOutputFunc(Fortify_OutputFuncPtr Output);
+void  Fortify_Disable(const char *file, unsigned long line);
+
+/* Fortify versions of the ANSI C memory allocation functions */
+void *Fortify_malloc(size_t size, const char *file, unsigned long line);
+void *Fortify_realloc(void *ptr, size_t new_size, const char *file, unsigned 
long line);
+void *Fortify_calloc(size_t num, size_t size, const char *file, unsigned long 
line);
+void  Fortify_free(void *uptr, const char *file, unsigned long line);
+
+/* Fortify versions of some non-ANSI C memory allocation functions */
+#ifdef FORTIFY_STRDUP
+    char *Fortify_strdup(const char *oldStr, const char *file, unsigned long 
line);
+#endif
+
+#ifdef __cplusplus
+/* Magic global variable */
+extern int gbl_FortifyMagic;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+#include <new.h>
+
+    /* Fortify versions of new and delete */
+    void *operator new(size_t size);
+    void *operator new(size_t size, const char *file, unsigned long line);
+    void  operator delete(void *pointer);
+    void  Fortify_PreDelete(const char *file, unsigned long line);
+    void  Fortify_PostDelete();
+
+    /* Some compilers use a different new operator for newing arrays.
+     * This includes GNU G++ (2.6.0) and Borland C++ (4.02)
+     */
+    #ifdef FORTIFY_PROVIDE_ARRAY_NEW
+        void *operator new[](size_t size);
+        void *operator new[](size_t size, const char *file, unsigned long 
line);
+    #endif
+
+    /* Some compilers provide a different delete operator for deleting arrays.
+     * This incldues GNU G++ (2.6.0)
+     */
+    #ifdef FORTIFY_PROVIDE_ARRAY_DELETE
+        void  operator delete[](void *pointer);
+    #endif
+
+#endif /* __cplusplus */
+
+#ifndef __FORTIFY_C__ /* Only define the macros if we're NOT in fortify.c */
+
+/* Add file and line information to the fortify calls */
+#ifdef FORTIFY
+    /* Core Fortify Functions */
+    #define Fortify_CheckAllMemory()       Fortify_CheckAllMemory(__FILE__, 
__LINE__)
+    #define Fortify_ListAllMemory()        Fortify_ListAllMemory (__FILE__, 
__LINE__)
+    #define Fortify_DumpAllMemory()        Fortify_DumpAllMemory (__FILE__, 
__LINE__)
+    #define Fortify_CheckPointer(ptr)      Fortify_CheckPointer(ptr, __FILE__, 
__LINE__)
+    #define Fortify_LabelPointer(ptr,str)  Fortify_LabelPointer(ptr, str, 
__FILE__, __LINE__)
+    #define Fortify_EnterScope()           Fortify_EnterScope(__FILE__, 
__LINE__)
+    #define Fortify_LeaveScope()           Fortify_LeaveScope(__FILE__, 
__LINE__)
+    #define Fortify_OutputStatistics()     Fortify_OutputStatistics(__FILE__, 
__LINE__)
+    #define Fortify_GetCurrentAllocation() 
Fortify_GetCurrentAllocation(__FILE__, __LINE__)
+    #define Fortify_SetAllocationLimit(x)  Fortify_SetAllocationLimit(x, 
__FILE__, __LINE__)    
+    #define Fortify_Disable()              Fortify_Disable(__FILE__, __LINE__)
+
+    /* Fortify versions of the ANSI C memory allocation functions */
+    #define malloc(size)                   Fortify_malloc(size, __FILE__, 
__LINE__)
+    #define realloc(ptr,new_size)          Fortify_realloc(ptr, new_size, 
__FILE__, __LINE__)
+    #define calloc(num,size)               Fortify_calloc(num, size, __FILE__, 
__LINE__)
+    #define free(ptr)                      Fortify_free(ptr, __FILE__, 
__LINE__)
+
+    /* Fortify versions of some non-ANSI C memory allocation functions */
+    #ifdef FORTIFY_STRDUP
+        #define strdup(ptr)                Fortify_strdup(ptr, __FILE__, 
__LINE__)
+    #endif
+
+    /* Fortify versions of new and delete */
+    #ifdef __cplusplus
+        #define Fortify_New                new(__FILE__, __LINE__)
+        #define Fortify_Delete             for(gbl_FortifyMagic = 1, \
+                                               Fortify_PreDelete(__FILE__, 
__LINE__); \
+                                               gbl_FortifyMagic; 
Fortify_PostDelete()) \
+                                                       gbl_FortifyMagic = 0, 
delete
+        #define new                        Fortify_New
+        #define delete                     Fortify_Delete
+    #endif /* __cplusplus */
+
+#else /* Define the special fortify functions away to nothing */
+
+    #define Fortify_CheckAllMemory()       0
+    #define Fortify_ListAllMemory()        0
+    #define Fortify_DumpAllMemory()        0
+    #define Fortify_CheckPointer(ptr)      1 
+    #define Fortify_LabelPointer(ptr,str)  
+    #define Fortify_SetOutputFunc()        0
+    #define Fortify_SetMallocFailRate(p)   0
+    #define Fortify_EnterScope()           0
+    #define Fortify_LeaveScope()           0
+    #define Fortify_OutputStatistics()     0
+    #define Fortify_GetCurrentAllocation() 0
+    #define Fortify_SetAllocationLimit(x)  0
+    #define Fortify_Disable()              0
+
+    #ifdef __cplusplus    
+        #define Fortify_New                    new
+        #define Fortify_Delete                 delete
+    #endif /* __cplusplus */
+
+#endif /*   FORTIFY     */
+#endif /* __FORTIFY_C__ */
+#endif /* __FORTIFY_H__ */
diff --git a/frontends/amiga/fortify/ufortify.h 
b/frontends/amiga/fortify/ufortify.h
new file mode 100755
index 0000000..478d6aa
--- /dev/null
+++ b/frontends/amiga/fortify/ufortify.h
@@ -0,0 +1,63 @@
+/*
+ * FILE:
+ *   ufortify.h
+ *
+ * DESCRIPTION:
+ *   User options for fortify. Changes to this file require fortify.c to be
+ * recompiled, but nothing else.
+ */
+
+#define FORTIFY_STORAGE              /* storage for public functions   */
+
+#define FORTIFY_ALIGNMENT        sizeof(double) /* Byte alignment of all 
memory blocks */
+
+#define FORTIFY_BEFORE_SIZE      32  /* Bytes to allocate before block */
+#define FORTIFY_BEFORE_VALUE   0xA3  /* Fill value before block        */
+                      
+#define FORTIFY_AFTER_SIZE       32  /* Bytes to allocate after block  */
+#define FORTIFY_AFTER_VALUE    0xA5  /* Fill value after block         */
+
+#define FORTIFY_FILL_ON_ALLOCATE               /* Nuke out malloc'd memory     
  */
+#define FORTIFY_FILL_ON_ALLOCATE_VALUE   0xA7  /* Value to initialize with     
  */
+
+#define FORTIFY_FILL_ON_DEALLOCATE             /* free'd memory is cleared     
  */
+#define FORTIFY_FILL_ON_DEALLOCATE_VALUE 0xA9  /* Value to de-initialize with  
  */
+
+#define FORTIFY_FILL_ON_CORRUPTION             /* Nuke out corrupted memory    
*/
+
+/* #define FORTIFY_CHECK_ALL_MEMORY_ON_ALLOCATE */
+/* #define FORTIFY_CHECK_ALL_MEMORY_ON_DEALLOCATE */
+#define FORTIFY_PARANOID_DEALLOCATE
+
+/* #define FORTIFY_WARN_ON_ZERO_MALLOC */ /* A debug is issued on a malloc(0) 
*/
+/* #define FORTIFY_FAIL_ON_ZERO_MALLOC */ /* A malloc(0) will fail            
*/
+
+#define FORTIFY_WARN_ON_ALLOCATE_FAIL    /* A debug is issued on a failed 
alloc  */
+#define FORTIFY_WARN_ON_FALSE_FAIL       /* See Fortify_SetAllocateFailRate    
  */
+#define FORTIFY_WARN_ON_SIZE_T_OVERFLOW  /* Watch for breaking the 64K limit 
in  */
+                                         /* some braindead architectures...    
  */
+
+#define FORTIFY_TRACK_DEALLOCATED_MEMORY
+#define FORTIFY_DEALLOCATED_MEMORY_LIMIT 1048576 /* Maximum amount of 
deallocated bytes to keep */
+/* #define FORTIFY_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+/* #define FORTIFY_VERBOSE_WARN_WHEN_DISCARDING_DEALLOCATED_MEMORY */
+
+/* #define FORTIFY_NO_PERCENT_P */       /* sprintf() doesn't support %p */
+/* #define FORTIFY_STRDUP       */       /* if you use non-ANSI strdup() */
+
+#define FORTIFY_LOCK()
+#define FORTIFY_UNLOCK()
+
+#define FORTIFY_DELETE_STACK_SIZE    256
+
+#ifdef __cplusplus                /* C++ only options go here */
+
+/*    #define FORTIFY_PROVIDE_ARRAY_NEW     */
+/*    #define FORTIFY_PROVIDE_ARRAY_DELETE  */
+
+/*    #define FORTIFY_AUTOMATIC_LOG_FILE */
+    #define FORTIFY_LOG_FILENAME            "fortify.log"
+    #include <iostream.h>
+    #define FORTIFY_FIRST_ERROR_FUNCTION    cout << "\a\a\aFortify Hit 
Generated!\n"
+
+#endif /* __cplusplus */


-----------------------------------------------------------------------


-- 
NetSurf Browser

_______________________________________________
netsurf-commits mailing list
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org

Reply via email to