Skip to content

Instantly share code, notes, and snippets.

@dev-zzo
Created February 10, 2016 13:31
Show Gist options
  • Save dev-zzo/47ff43478186d15eb8f0 to your computer and use it in GitHub Desktop.
Save dev-zzo/47ff43478186d15eb8f0 to your computer and use it in GitHub Desktop.
Global pointers misuse

Global pointer variables misused in C programs

TL;DR: load global variables into local ones before use.

I've spotted a quite widespread misuse of global pointer variables. The issue is easily demonstrated by the following simplified example.

struct some_type_t {
    int a1;
    int a2;
    int a3;
};

struct some_type_t *p_global;

void f1()
{
    p_global->a1 = 1;
    p_global->a2 = 2;
    p_global->a3 = 3;
}

void f2()
{
    struct some_type_t *t_global = p_global;
    t_global->a1 = 1;
    t_global->a2 = 2;
    t_global->a3 = 3;
}

Which gets compiled into the following, using MSVC 2010:

; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 

	TITLE	C:\Users\User\Projects\test.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

_DATA	SEGMENT
COMM	_p_global:DWORD
_DATA	ENDS
PUBLIC	_f1
; Function compile flags: /Ogtpy
; File c:\users\user\projects\test.c
;	COMDAT _f1
_TEXT	SEGMENT
_f1	PROC						; COMDAT

; 12   :     p_global->a1 = 1;

  00000	a1 00 00 00 00	 mov	 eax, DWORD PTR _p_global
  00005	c7 00 01 00 00
	00		 mov	 DWORD PTR [eax], 1

; 13   :     p_global->a2 = 2;

  0000b	8b 0d 00 00 00
	00		 mov	 ecx, DWORD PTR _p_global
  00011	c7 41 04 02 00
	00 00		 mov	 DWORD PTR [ecx+4], 2

; 14   :     p_global->a3 = 3;

  00018	8b 15 00 00 00
	00		 mov	 edx, DWORD PTR _p_global
  0001e	c7 42 08 03 00
	00 00		 mov	 DWORD PTR [edx+8], 3

; 15   : }

  00025	c3		 ret	 0
_f1	ENDP
_TEXT	ENDS
PUBLIC	_f2
; Function compile flags: /Ogtpy
;	COMDAT _f2
_TEXT	SEGMENT
_f2	PROC						; COMDAT

; 19   :     struct some_type_t *t_global = p_global;

  00000	a1 00 00 00 00	 mov	 eax, DWORD PTR _p_global

; 20   :     t_global->a1 = 1;

  00005	c7 00 01 00 00
	00		 mov	 DWORD PTR [eax], 1

; 21   :     t_global->a2 = 2;

  0000b	c7 40 04 02 00
	00 00		 mov	 DWORD PTR [eax+4], 2

; 22   :     t_global->a3 = 3;

  00012	c7 40 08 03 00
	00 00		 mov	 DWORD PTR [eax+8], 3

; 23   : }

  00019	c3		 ret	 0
_f2	ENDP
_TEXT	ENDS
END

Moral of the story is quite obvious: loading the variable from global to local allows the compiler to shave off reloads on each use -- as it can't infer the global won't change between uses.

And now for a real life example:

INIT:BFA33B6C ; =============== S U B R O U T I N E =======================================
INIT:BFA33B6C
INIT:BFA33B6C
INIT:BFA33B6C ; _DWORD __stdcall InitFunctionTables()
INIT:BFA33B6C _InitFunctionTables@0 proc near         ; CODE XREF: Win32UserInitialize()+1EE�p
INIT:BFA33B6C                 mov     eax, _gpsi
INIT:BFA33B71                 mov     dword ptr [eax+88h], offset _xxxSBWndProc@16 ; xxxSBWndProc(x,x,x,x)
INIT:BFA33B7B                 mov     ecx, _gpsi
INIT:BFA33B81                 mov     eax, offset _xxxDefWindowProc@16 ; xxxDefWindowProc(x,x,x,x)
INIT:BFA33B86                 mov     [ecx+8Ch], eax
INIT:BFA33B8C                 mov     ecx, _gpsi
INIT:BFA33B92                 mov     dword ptr [ecx+90h], offset _xxxMenuWindowProc@16 ; xxxMenuWindowProc(x,x,x,x)
INIT:BFA33B9C                 mov     ecx, _gpsi
INIT:BFA33BA2                 mov     dword ptr [ecx+94h], offset _xxxDesktopWndProc@16 ; xxxDesktopWndProc(x,x,x,x)
INIT:BFA33BAC                 mov     ecx, _gpsi
INIT:BFA33BB2                 mov     [ecx+98h], eax
INIT:BFA33BB8                 mov     ecx, _gpsi
INIT:BFA33BBE                 mov     [ecx+9Ch], eax
INIT:BFA33BC4                 mov     ecx, _gpsi
INIT:BFA33BCA                 mov     eax, 0F8h
INIT:BFA33BCF                 mov     [ecx+0A4h], ax
INIT:BFA33BD6                 mov     ecx, _gpsi
INIT:BFA33BDC                 add     eax, 0FFFFFFB8h
INIT:BFA33BDF                 mov     [ecx+0A6h], ax
INIT:BFA33BE6                 mov     ecx, _gpsi
INIT:BFA33BEC                 mov     eax, 0B4h
INIT:BFA33BF1                 mov     [ecx+0A8h], ax
INIT:BFA33BF8                 xor     eax, eax
INIT:BFA33BFA
INIT:BFA33BFA loc_BFA33BFA:                           ; CODE XREF: InitFunctionTables()+A5�j
INIT:BFA33BFA                 mov     edx, _gpsi
INIT:BFA33C00                 mov     ecx, eax
INIT:BFA33C02                 and     ecx, 1Fh
INIT:BFA33C05                 inc     eax
INIT:BFA33C06                 mov     dword ptr [edx+ecx*4+8], offset _EngSetPointerTag@20 ; EngSetPointerTag(x,x,x,x,x)
INIT:BFA33C0E                 cmp     eax, 20h
INIT:BFA33C11                 jb      short loc_BFA33BFA
INIT:BFA33C13                 mov     eax, _gpsi
INIT:BFA33C18                 mov     dword ptr [eax+8], offset _xxxWrapSBWndProc@20 ; xxxWrapSBWndProc(x,x,x,x,x)
INIT:BFA33C1F                 mov     ecx, _gpsi
INIT:BFA33C25                 mov     eax, offset _xxxWrapRealDefWindowProc@20 ; xxxWrapRealDefWindowProc(x,x,x,x,x)
INIT:BFA33C2A                 mov     [ecx+0Ch], eax
INIT:BFA33C2D                 mov     ecx, _gpsi
INIT:BFA33C33                 mov     dword ptr [ecx+10h], offset _xxxWrapMenuWindowProc@20 ; xxxWrapMenuWindowProc(x,x,x,x,x)
INIT:BFA33C3A                 mov     ecx, _gpsi
INIT:BFA33C40                 mov     dword ptr [ecx+14h], offset _xxxWrapDesktopWndProc@20 ; xxxWrapDesktopWndProc(x,x,x,x,x)
INIT:BFA33C47                 mov     ecx, _gpsi
INIT:BFA33C4D                 mov     [ecx+18h], eax
INIT:BFA33C50                 mov     ecx, _gpsi
INIT:BFA33C56                 mov     [ecx+1Ch], eax
INIT:BFA33C59                 mov     eax, _gpsi
INIT:BFA33C5E                 mov     dword ptr [eax+64h], offset _xxxWrapSendMessage@20 ; xxxWrapSendMessage(x,x,x,x,x)
INIT:BFA33C65                 mov     eax, _gpsi
INIT:BFA33C6A                 mov     dword ptr [eax+4Ch], offset _fnHkINLPCWPEXSTRUCT@20 ; fnHkINLPCWPEXSTRUCT(x,x,x,x,x)
INIT:BFA33C71                 mov     eax, _gpsi
INIT:BFA33C76                 mov     dword ptr [eax+50h], offset _fnHkINLPCWPRETEXSTRUCT@20 ; fnHkINLPCWPRETEXSTRUCT(x,x,x,x,x)
INIT:BFA33C7D                 mov     eax, _gpsi
INIT:BFA33C82                 mov     dword ptr [eax+68h], offset _xxxSendMessageFF@20 ; xxxSendMessageFF(x,x,x,x,x)
INIT:BFA33C89                 mov     eax, _gpsi
INIT:BFA33C8E                 mov     dword ptr [eax+6Ch], offset _xxxSendMessageEx@20 ; xxxSendMessageEx(x,x,x,x,x)
INIT:BFA33C95                 mov     eax, _gpsi
INIT:BFA33C9A                 mov     dword ptr [eax+70h], offset _xxxWrapCallWindowProc@20 ; xxxWrapCallWindowProc(x,x,x,x,x)
INIT:BFA33CA1                 mov     eax, _gpsi
INIT:BFA33CA6                 mov     dword ptr [eax+74h], offset _xxxWrapSendMessageBSM@20 ; xxxWrapSendMessageBSM(x,x,x,x,x)
INIT:BFA33CAD                 mov     eax, _gpsi
INIT:BFA33CB2                 mov     dword ptr [eax+20h], offset _xxxWrapSwitchWndProc@20 ; xxxWrapSwitchWndProc(x,x,x,x,x)
INIT:BFA33CB9                 mov     eax, _gpsi
INIT:BFA33CBE                 mov     dword ptr [eax+7Ch], offset _xxxWrapSendNotifyMessage@20 ; xxxWrapSendNotifyMessage(x,x,x,x,x)
INIT:BFA33CC5                 mov     eax, _gpsi
INIT:BFA33CCA                 mov     dword ptr [eax+80h], offset _xxxWrapSendMessageCallback@20 ; xxxWrapSendMessageCallback(x,x,x,x,x)
INIT:BFA33CD4                 retn
INIT:BFA33CD4 _InitFunctionTables@0 endp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment