c++ - What does this cast from long in a union to char* and back do? -
i examining code of simple executable packer writes section executable unpacks during startup, when stumbled upon piece of code:
void setdistance( unsigned long size ) { char* set = (((char *)i)+punpacker->virtualaddress); union { short sh[2]; long l; } conv; conv.l = size; conv.sh[0] = 0; unpacker_set(set, (char *)(&conv.l), 4, text_distance); }
size distance unpacker code in memory beginning of section supposed unpacked. in loader code defined unsigned long. unpacker_set on other hand has code:
void inline unpacker_set( char* at, char* what, size_t size, unsigned long sig ) { dword oldprotect; unsigned char *set = (unsigned char *)at; while(*((unsigned long*)(set)) != sig) set++; if(virtualprotect(set, size, page_readwrite, &oldprotect) == true) for(unsigned i=0; i<size; i++) *(set+i) = *(what+i); }
although understand second routine replaces value unpacker code, know why hassle union done. appreciated.
probably best way understand code write minimal test case , see does:
#include <iostream> void f() { union { short sh[2]; long l ; } conv ; conv.l = 100000000 ; std::cout << std::hex << conv.l << std::endl ; conv.sh[0] = 0 ; std::cout << std::hex << conv.l << std::endl ; } int main() { f() ; }
the output see follows:
5f5e100 5f50000
so code intention looks trying mask out higher order bits of size, although ugly , unlikely portable.
as david pointed out should aware of strict aliasing. article type-punning , strict-aliasing better since has solid examples of real world issues using union
s. in order assure code works expected assuming gcc
or clang
need pass in following command line argument -fno-strict-aliasing
.
Comments
Post a Comment