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