Browse Source

Catching null pointer exceptions from the region start, so that the pointer can move and still be caught as null.

David Piuva 2 years ago
parent
commit
550114772b

+ 2 - 2
Source/DFPSR/base/SafePointer.cpp

@@ -33,9 +33,9 @@ void dsr::assertNonNegativeSize(intptr_t size) {
 }
 }
 
 
 void dsr::assertInsideSafePointer(const char* method, const char* name, const uint8_t* pointer, const uint8_t* data, const uint8_t* regionStart, const uint8_t* regionEnd, intptr_t claimedSize, intptr_t elementSize) {
 void dsr::assertInsideSafePointer(const char* method, const char* name, const uint8_t* pointer, const uint8_t* data, const uint8_t* regionStart, const uint8_t* regionEnd, intptr_t claimedSize, intptr_t elementSize) {
-	if (pointer < regionStart || pointer + claimedSize > regionEnd) {
+	if (regionStart == nullptr || pointer < regionStart || pointer + claimedSize > regionEnd) {
 		String message;
 		String message;
-		if (data == nullptr) {
+		if (regionStart == nullptr) {
 			string_append(message, U"\n _____________________ SafePointer null exception! _____________________\n");
 			string_append(message, U"\n _____________________ SafePointer null exception! _____________________\n");
 		} else {
 		} else {
 			string_append(message, U"\n _________________ SafePointer out of bound exception! _________________\n");
 			string_append(message, U"\n _________________ SafePointer out of bound exception! _________________\n");

+ 17 - 0
Source/DFPSR/base/SafePointer.h

@@ -21,6 +21,23 @@
 //    3. This notice may not be removed or altered from any source
 //    3. This notice may not be removed or altered from any source
 //    distribution.
 //    distribution.
 
 
+// If you get segmentation faults despite using SafePointer, then check the following.
+// * Are you compiling all of your code in debug mode?
+//   The release mode does not perform SafePointer checks, because it is supposed to be zero overhead by letting the compiler inline the pointers.
+// * Did you create a SafePointer from a memory region that you do not have access to, expired stack memory, or a region larger than the allocation?
+//   SafePointer can not know which memory is safe to call if you do not give it correct information.
+//   If the pointer was created without an allocation, make sure that regionStart is nullptr and claimedSize is zero.
+// * Did you deallocate the memory before using the SafePointer?
+//   SafePointer can not keep the allocation alive, because that would require counting references in both debug and release.
+
+// To stay safe when using SafePointer:
+// * Compile in debug mode by habit, until it is time for profiling or relase.
+//   The operating system can not detect out of bound access in stack memory or arena allocations, so it may silently corrupt the memory without being caught if safety is disabled.
+// * Let the Buffer create the safe pointer for you to prevent accidentally giving the wrong size, or use the default constructor for expressing null.
+//   If you only need a part of the buffer's memory, use the slice function to get a subset of the memory with bound checks on construction.
+// * Either create a SafePointer when needed within the buffer's scope, or store both in the same structure.
+//   This makes sure that the allocation is not freed while the pointer still exists.
+
 #ifndef DFPSR_SAFE_POINTER
 #ifndef DFPSR_SAFE_POINTER
 #define DFPSR_SAFE_POINTER
 #define DFPSR_SAFE_POINTER
 
 

+ 1 - 1
Source/test/tests/SafePointerTest.cpp

@@ -10,7 +10,7 @@ START_TEST(SafePointer)
 	uint8_t allocation[3][bufferSize];
 	uint8_t allocation[3][bufferSize];
 	// Run the algorithm for each byte offset relative to the alignment
 	// Run the algorithm for each byte offset relative to the alignment
 	for (int offset = 0; offset < alignment; offset++) {
 	for (int offset = 0; offset < alignment; offset++) {
-		// The SafePointer class will emulate the behaviour of a raw data pointer while providing full bound checks in debug mode.
+		// The SafePointer should be inlined into a raw pointer in relase mode while providing full bound checks in debug mode.
 		SafePointer<int32_t> bufferA("bufferA", (int32_t*)(allocation[0] + offset), dataSize);
 		SafePointer<int32_t> bufferA("bufferA", (int32_t*)(allocation[0] + offset), dataSize);
 		SafePointer<int32_t> bufferB("bufferB", (int32_t*)(allocation[1] + offset), dataSize);
 		SafePointer<int32_t> bufferB("bufferB", (int32_t*)(allocation[1] + offset), dataSize);
 		SafePointer<int32_t> bufferC("bufferC", (int32_t*)(allocation[2] + offset), dataSize);
 		SafePointer<int32_t> bufferC("bufferC", (int32_t*)(allocation[2] + offset), dataSize);