[quake3-commits] r1888 - trunk/code/qcommon

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Feb 10 13:45:28 EST 2011


Author: thilo
Date: 2011-02-10 13:45:28 -0500 (Thu, 10 Feb 2011)
New Revision: 1888

Modified:
   trunk/code/qcommon/vm_powerpc.c
   trunk/code/qcommon/vm_sparc.c
   trunk/code/qcommon/vm_x86.c
   trunk/code/qcommon/vm_x86_64.c
   trunk/code/qcommon/vm_x86_64_assembler.c
Log:
- Use MAP_FAILED error code for check whether mmap() was successful
- Replace various malloc() with Z_Malloc
- Fix several memory leaks when VM compilation failed and Com_Error is called
- Make failed mmap/VirtualAlloc/malloc calls fatal


Modified: trunk/code/qcommon/vm_powerpc.c
===================================================================
--- trunk/code/qcommon/vm_powerpc.c	2011-02-09 05:51:33 UTC (rev 1887)
+++ trunk/code/qcommon/vm_powerpc.c	2011-02-10 18:45:28 UTC (rev 1888)
@@ -1837,7 +1837,7 @@
 	unsigned char *dataAndCode = mmap( NULL, codeLength,
 		PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0 );
 
-	if ( ! dataAndCode )
+	if (dataAndCode == MAP_FAILED)
 		DIE( "Not enough memory" );
 
 	ppc_instruction_t *codeNow, *codeBegin;

Modified: trunk/code/qcommon/vm_sparc.c
===================================================================
--- trunk/code/qcommon/vm_sparc.c	2011-02-09 05:51:33 UTC (rev 1887)
+++ trunk/code/qcommon/vm_sparc.c	2011-02-10 18:45:28 UTC (rev 1888)
@@ -1427,7 +1427,7 @@
 
 	data_and_code = mmap(NULL, code_length, PROT_READ | PROT_WRITE,
 			     MAP_SHARED | MAP_ANONYMOUS, -1, 0);
-	if (!data_and_code)
+	if (data_and_code == MAP_FAILED)
 		DIE("Not enough memory");
 
 	code_now = code_begin = (unsigned int *)

Modified: trunk/code/qcommon/vm_x86.c
===================================================================
--- trunk/code/qcommon/vm_x86.c	2011-02-09 05:51:33 UTC (rev 1887)
+++ trunk/code/qcommon/vm_x86.c	2011-02-10 18:45:28 UTC (rev 1888)
@@ -53,6 +53,7 @@
 
 */
 
+#define VMFREE_BUFFERS() {Z_Free(buf); Z_Free(jused);}
 static	byte	*buf = NULL;
 static	byte	*jused = NULL;
 static	int		compiledOfs = 0;
@@ -289,6 +290,7 @@
 		return c - '0';
 	}
 
+	VMFREE_BUFFERS();
 	Com_Error( ERR_DROP, "Hex: bad char '%c'", c );
 
 	return 0;
@@ -408,6 +410,7 @@
 #define JUSED(x) \
 	do { \
 		if (x < 0 || x >= jusedSize) { \
+		        VMFREE_BUFFERS(); \
 			Com_Error( ERR_DROP, \
 					"VM_CompileX86: jump target out of range at offset %d", pc ); \
 		} \
@@ -429,7 +432,7 @@
 
 	// allocate a very large temp buffer, we will shrink it later
 	maxLength = header->codeLength * 8;
-	buf = Z_Malloc( maxLength );
+	buf = Z_Malloc(maxLength);
 	jused = Z_Malloc(jusedSize);
 	
 	Com_Memset(jused, 0, jusedSize);
@@ -454,16 +457,21 @@
 
 	LastCommand = LAST_COMMAND_NONE;
 
-	while ( instruction < header->instructionCount ) {
-		if ( compiledOfs > maxLength - 16 ) {
-			Com_Error( ERR_FATAL, "VM_CompileX86: maxLength exceeded" );
+	while(instruction < header->instructionCount)
+	{
+		if(compiledOfs > maxLength - 16)
+		{
+	        	VMFREE_BUFFERS();
+			Com_Error(ERR_DROP, "VM_CompileX86: maxLength exceeded");
 		}
 
 		vm->instructionPointers[ instruction ] = compiledOfs;
 		instruction++;
 
-		if ( pc > header->codeLength ) {
-			Com_Error( ERR_FATAL, "VM_CompileX86: pc > header->codeLength" );
+		if(pc > header->codeLength)
+		{
+		        VMFREE_BUFFERS();
+			Com_Error(ERR_DROP, "VM_CompileX86: pc > header->codeLength");
 		}
 
 		op = code[ pc ];
@@ -1075,7 +1083,8 @@
 			Emit4( (int)vm->instructionPointers );
 			break;
 		default:
-			Com_Error( ERR_DROP, "VM_CompileX86: bad opcode %i at offset %i", op, pc );
+		        VMFREE_BUFFERS();
+			Com_Error(ERR_DROP, "VM_CompileX86: bad opcode %i at offset %i", op, pc);
 		}
 		pop0 = pop1;
 		pop1 = op;
@@ -1086,13 +1095,13 @@
 	vm->codeLength = compiledOfs;
 #ifdef VM_X86_MMAP
 	vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
-	if(vm->codeBase == (void*)-1)
-		Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory");
+	if(vm->codeBase == MAP_FAILED)
+		Com_Error(ERR_FATAL, "VM_CompileX86: can't mmap memory");
 #elif _WIN32
 	// allocate memory with EXECUTE permissions under windows.
 	vm->codeBase = VirtualAlloc(NULL, compiledOfs, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 	if(!vm->codeBase)
-		Com_Error(ERR_DROP, "VM_CompileX86: VirtualAlloc failed");
+		Com_Error(ERR_FATAL, "VM_CompileX86: VirtualAlloc failed");
 #else
 	vm->codeBase = malloc(compiledOfs);
 #endif
@@ -1101,14 +1110,14 @@
 
 #ifdef VM_X86_MMAP
 	if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC))
-		Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed");
+		Com_Error(ERR_FATAL, "VM_CompileX86: mprotect failed");
 #elif _WIN32
 	{
 		DWORD oldProtect = 0;
 		
 		// remove write permissions.
 		if(!VirtualProtect(vm->codeBase, compiledOfs, PAGE_EXECUTE_READ, &oldProtect))
-			Com_Error(ERR_DROP, "VM_CompileX86: VirtualProtect failed");
+			Com_Error(ERR_FATAL, "VM_CompileX86: VirtualProtect failed");
 	}
 #endif
 

Modified: trunk/code/qcommon/vm_x86_64.c
===================================================================
--- trunk/code/qcommon/vm_x86_64.c	2011-02-09 05:51:33 UTC (rev 1887)
+++ trunk/code/qcommon/vm_x86_64.c	2011-02-10 18:45:28 UTC (rev 1888)
@@ -54,6 +54,8 @@
 #define Dfprintf(args...)
 #endif
 
+#define VM_FREEBUFFERS(vm) {assembler_init(0); VM_Destroy_Compiled(vm);}
+
 void assembler_set_output(char* buf);
 size_t assembler_get_code_size(void);
 void assembler_init(int pass);
@@ -251,6 +253,7 @@
 
 #define CHECK_INSTR(nr) \
 	do { if(nr < 0 || nr >= header->instructionCount) { \
+		VM_FREEBUFFERS(vm); \
 		Com_Error( ERR_DROP, \
 			"%s: jump target 0x%x out of range at offset %d", __func__, nr, pc ); \
 	} } while(0)
@@ -429,6 +432,8 @@
 
 	// const optimization
 	unsigned got_const = 0, const_value = 0;
+	
+	vm->codeBase = NULL;
 
 	gettimeofday(&tvstart, NULL);
 
@@ -441,15 +446,17 @@
 
 		#ifdef VM_X86_64_MMAP
 			vm->codeBase = mmap(NULL, compiledOfs, PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
-			if(vm->codeBase == (void*)-1)
-				Com_Error(ERR_DROP, "VM_CompileX86: can't mmap memory");
+			if(vm->codeBase == MAP_FAILED)
+				Com_Error(ERR_FATAL, "VM_CompileX86_64: can't mmap memory");
 		#elif __WIN64__
 			// allocate memory with write permissions under windows.
 			vm->codeBase = VirtualAlloc(NULL, compiledOfs, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
 			if(!vm->codeBase)
-				Com_Error(ERR_DROP, "VM_CompileX86: VirtualAlloc failed");
+				Com_Error(ERR_FATAL, "VM_CompileX86_64: VirtualAlloc failed");
 		#else
 			vm->codeBase = malloc(compiledOfs);
+			if(!vm_codeBase)
+				Com_Error(ERR_FATAL, "VM_CompileX86_64: Failed to allocate memory");
 		#endif
 
 		assembler_set_output((char*)vm->codeBase);
@@ -930,7 +937,9 @@
 
 	}
 
-	if(got_const) {
+	if(got_const)
+	{
+		VM_FREEBUFFERS(vm);
 		Com_Error(ERR_DROP, "leftover const\n");
 	}
 
@@ -943,14 +952,14 @@
 
 	#ifdef VM_X86_64_MMAP
 		if(mprotect(vm->codeBase, compiledOfs, PROT_READ|PROT_EXEC))
-			Com_Error(ERR_DROP, "VM_CompileX86: mprotect failed");
+			Com_Error(ERR_FATAL, "VM_CompileX86_64: mprotect failed");
 	#elif __WIN64__
 		{
 			DWORD oldProtect = 0;
 			
 			// remove write permissions; give exec permision
 			if(!VirtualProtect(vm->codeBase, compiledOfs, PAGE_EXECUTE_READ, &oldProtect))
-				Com_Error(ERR_DROP, "VM_CompileX86: VirtualProtect failed");
+				Com_Error(ERR_FATAL, "VM_CompileX86_64: VirtualProtect failed");
 		}
 	#endif
 
@@ -987,11 +996,16 @@
 
 void VM_Destroy_Compiled(vm_t* self)
 {
-#ifdef _WIN32
-	VirtualFree(self->codeBase, 0, MEM_RELEASE);
+	if(self && self->codeBase)
+	{
+#ifdef VM_X86_64_MMAP
+		munmap(self->codeBase, self->codeLength);
+#elif __WIN64__
+		VirtualFree(self->codeBase, 0, MEM_RELEASE);
 #else
-	munmap(self->codeBase, self->codeLength);
+		free(self->codeBase);
 #endif
+	}
 }
 
 /*

Modified: trunk/code/qcommon/vm_x86_64_assembler.c
===================================================================
--- trunk/code/qcommon/vm_x86_64_assembler.c	2011-02-09 05:51:33 UTC (rev 1887)
+++ trunk/code/qcommon/vm_x86_64_assembler.c	2011-02-10 18:45:28 UTC (rev 1888)
@@ -244,10 +244,10 @@
 	int labellen;
 	
 	i %= sizeof(labelhash)/sizeof(labelhash[0]);
-	h = malloc(sizeof(struct hashentry));
+	h = Z_Malloc(sizeof(struct hashentry));
 	
 	labellen = strlen(label) + 1;
-	h->label = malloc(labellen);
+	h->label = Z_Malloc(labellen);
 	memcpy(h->label, label, labellen);
 	
 	h->address = address;
@@ -282,8 +282,8 @@
 		while(h)
 		{
 			struct hashentry* next = h->next;
-			free(h->label);
-			free(h);
+			Z_Free(h->label);
+			Z_Free(h);
 			h = next;
 			++n;
 		}



More information about the quake3-commits mailing list