From 16e6fe593ba12c90170db4e0f1aa135c3bfbd43f Mon Sep 17 00:00:00 2001 From: fadedreamz Date: Sun, 4 Dec 2016 21:06:09 -0500 Subject: [PATCH] fixed memory address access issue on win64 build Signed-off-by: fadedreamz --- OSlibs/win/mingw.h | 24 +++++++++++++++++++++++- crypto777/iguana_OS.c | 9 +++++++++ iguana/iguana_accept.c | 6 ++++++ iguana/iguana_blocks.c | 13 +++++++++++++ iguana/iguana_init.c | 5 ++++- iguana/iguana_peers.c | 3 ++- iguana/iguana_ramchain.c | 29 +++++++++++++++++++++++++++++ iguana/iguana_tx.c | 38 ++++++++++++++++++++++++++++++++++++-- iguana/iguana_txidfind.c | 10 ++++++++++ includes/iguana_funcs.h | 9 +++++++++ includes/iguana_structs.h | 20 ++++++++++++++++++++ 11 files changed, 161 insertions(+), 5 deletions(-) diff --git a/OSlibs/win/mingw.h b/OSlibs/win/mingw.h index 0ec007c21..6be81f99b 100755 --- a/OSlibs/win/mingw.h +++ b/OSlibs/win/mingw.h @@ -28,9 +28,22 @@ * are copied from linux man pages. A poll() macro is defined to * call the version in mingw.c. */ -#define POLLIN 0x0001 /* There is data to read */ + #define POLLPRI 0x0002 /* There is urgent data to read */ +#if defined(_M_X64) + /* + * when we are using WSAPoll() with window's struct pollfd struct + * we need to update the value for POLLIN and POLLOUT according to window's + * WSAPoll() return values + * @author - fadedreamz@gmail.com + */ +//TODO: need to update other values to match with WSAPoll() function +#define POLLIN POLLRDNORM | POLLRDBAND /* There is data to read */ +#define POLLOUT POLLWRNORM /* Writing now will not block */ +#else +#define POLLIN 0x0001 /* There is data to read */ #define POLLOUT 0x0004 /* Writing now will not block */ +#endif #define POLLERR 0x0008 /* Error condition */ #define POLLHUP 0x0010 /* Hung up */ #define POLLNVAL 0x0020 /* Invalid request: fd not open */ @@ -51,7 +64,16 @@ struct pollfd { }; #endif +#if defined(_M_X64) +/* +* we want to use the window's poll function if poll() is invoked in win64 +* as we are using window's pollfd struct when we are using x64 +* @author - fadedreamz@gmail.com +*/ +#define poll(x, y, z) WSAPoll(x, y, z) +#else #define poll(x, y, z) win32_poll(x, y, z) +#endif /* These wrappers do nothing special except set the global errno variable if * an error occurs (winsock doesn't do this by default). They set errno diff --git a/crypto777/iguana_OS.c b/crypto777/iguana_OS.c index d53a0ccbd..0032a8886 100755 --- a/crypto777/iguana_OS.c +++ b/crypto777/iguana_OS.c @@ -446,7 +446,16 @@ void *iguana_memalloc(struct OS_memspace *mem,long size,int32_t clearflag) #endif if ( (mem->used + size) <= mem->totalsize ) { + /* + * solution to calculate memory address in a portable way + * in all platform sizeof(char) / sizeof(uchar) == 1 + * @author - fadedreamz@gmail.com + */ +#if defined(_M_X64) + ptr = (void *)((unsigned char *)mem->ptr + mem->used); +#else ptr = (void *)(long)(((long)mem->ptr + mem->used)); +#endif mem->used += size; if ( size*clearflag != 0 ) memset(ptr,0,size); diff --git a/iguana/iguana_accept.c b/iguana/iguana_accept.c index 63d69787e..b3eaa07be 100755 --- a/iguana/iguana_accept.c +++ b/iguana/iguana_accept.c @@ -38,6 +38,7 @@ int32_t iguana_acceptspoll(uint8_t *buf,int32_t bufsize,struct iguana_accept *ac * 2^11*sizeof(struct fd) for win64 bit gives a very big number * for that reason it cannot allocate memory from stack * so the solution is to allocate memory from heap, instead of stack + * @author - fadedreamz@gmail.com */ #if defined(_M_X64) struct pollfd * fds; @@ -89,6 +90,11 @@ int32_t iguana_acceptspoll(uint8_t *buf,int32_t bufsize,struct iguana_accept *ac } } +/** +* graceful memory release, because we allocated memory on heap, +* so we are releasing it here +* @author - fadedreamz@gmail.com +*/ #if defined(_M_X64) free(fds); #endif diff --git a/iguana/iguana_blocks.c b/iguana/iguana_blocks.c index 64bf189d2..8b179b2c1 100755 --- a/iguana/iguana_blocks.c +++ b/iguana/iguana_blocks.c @@ -313,8 +313,21 @@ int32_t iguana_blockROsize(uint8_t zcash) void *iguana_blockzcopyRO(uint8_t zcash,struct iguana_blockRO *dest,int32_t desti,struct iguana_blockRO *src,int32_t srci) { int32_t bROsize = iguana_blockROsize(zcash); +/** +* The memory address calculation was done in a non-portable way using +* long value which has 4 bytes in 64bit windows (causing invalide memory address) +* due to data truncation, +* the solution is to use portable way to calculate the address +* in all platform sizeof(char) / sizeof(uchar) == 1 +* @author - fadedreamz@gmail.com +*/ +#if defined(_M_X64) + dest = (void *)((unsigned char *)dest + desti*bROsize); + src = (void *)((unsigned char *)src + srci*bROsize); +#else dest = (void *)((long)dest + desti*bROsize); src = (void *)((long)src + srci*bROsize); +#endif memcpy(dest,src,bROsize); return(src); } diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index b18de05cc..5d07685ba 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -613,7 +613,10 @@ struct iguana_info *iguana_coinstart(struct supernet_info *myinfo,struct iguana_ for (j=0; j<2; j++) { - // fadedreamz@gmail.com + /** + * macro switch for easy debug from Visual Studio IDE + * @author-fadedreamz@gmail.com + */ #if defined(WIN32) && defined(_DEBUG) sprintf(fname, "%s/%s/%s_%s%s.txt", "iguana", GLOBAL_CONFSDIR, coin->symbol, j == 0 ? "" : "old", (iter == 0) ? "peers" : "hdrs"), OS_compatible_path(fname); #else diff --git a/iguana/iguana_peers.c b/iguana/iguana_peers.c index 65049f9df..f981cc82d 100755 --- a/iguana/iguana_peers.c +++ b/iguana/iguana_peers.c @@ -1305,7 +1305,8 @@ void iguana_dedicatedloop(struct supernet_info *myinfo,struct iguana_info *coin, memset(&fds,0,sizeof(fds)); fds.fd = addr->usock; fds.events |= (POLLOUT | POLLIN); - if ( poll(&fds,1,timeout) > 0 && (fds.revents & POLLOUT) != 0 ) + + if ( poll(&fds,1,timeout) > 0 && (fds.revents & POLLOUT) != 0 ) { flag += iguana_pollsendQ(coin,addr); if ( addr->dead != 0 ) diff --git a/iguana/iguana_ramchain.c b/iguana/iguana_ramchain.c index 024da170e..d94078751 100755 --- a/iguana/iguana_ramchain.c +++ b/iguana/iguana_ramchain.c @@ -1326,7 +1326,16 @@ int32_t iguana_Xspendmap(struct iguana_info *coin,struct iguana_ramchain *ramcha sprintf(fname,"%s/%s%s/spends/%s.%d",GLOBAL_DBDIR,iter==0?"ro/":"",coin->symbol,bits256_str(str,bp->hashes[0]),bp->bundleheight); if ( (ptr= OS_mapfile(fname,&filesize,0)) != 0 ) { +#if defined(_M_X64) + /* + * calculate the address in a portable manner + * in all platform sizeof(char) / sizeof(uchar) == 1 + * @author - fadedreamz@gmail.com + */ + ramchain->Xspendinds = (void *)((unsigned char *)ptr + sizeof(sha256)); +#else ramchain->Xspendinds = (void *)((long)ptr + sizeof(sha256)); +#endif if ( bp->Xvalid == 0 ) vcalc_sha256(0,sha256.bytes,(void *)ramchain->Xspendinds,(int32_t)(filesize - sizeof(sha256))); ramchain->from_roX = (iter == 0); @@ -1399,7 +1408,17 @@ struct iguana_ramchain *_iguana_ramchain_map(struct supernet_info *myinfo,struct if ( ramchain->fileptr != 0 && ramchain->filesize > 0 ) { // verify hashes + + /* + * calculate the address in a portable manner + * in all platform sizeof(char) / sizeof(uchar) == 1 + * @author - fadedreamz@gmail.com + */ +#if defined(_M_X64) + ramchain->H.data = rdata = (void *)((unsigned char *)ramchain->fileptr + fpos); +#else ramchain->H.data = rdata = (void *)(long)((long)ramchain->fileptr + fpos); +#endif ramchain->H.ROflag = 1; ramchain->expanded = expanded; ramchain->numblocks = (bp == 0) ? 1 : bp->n; @@ -2421,7 +2440,17 @@ int32_t iguana_mapchaininit(char *fname,struct iguana_info *coin,struct iguana_r memset(mapchain,0,sizeof(*mapchain)); mapchain->fileptr = ptr; mapchain->filesize = filesize; + + /* + * calculate the address in a portable manner + * in all platform sizeof(char) / sizeof(uchar) == 1 + * @author - fadedreamz@gmail.com + */ +#if defined(_M_X64) + mapchain->H.data = (void *)((unsigned char *)ptr + block->fpos); +#else mapchain->H.data = (void *)(long)((long)ptr + block->fpos); +#endif mapchain->H.ROflag = 1; if ( ptr == 0 || block->fpos > filesize ) { diff --git a/iguana/iguana_tx.c b/iguana/iguana_tx.c index 3bfc95324..c58b7c56d 100755 --- a/iguana/iguana_tx.c +++ b/iguana/iguana_tx.c @@ -15,14 +15,28 @@ #include "iguana777.h" -int32_t iguana_scriptdata(struct iguana_info *coin,uint8_t *scriptspace,long fileptr[2],char *fname,uint64_t scriptpos,int32_t scriptlen) +#if defined(_M_X64) + /* + * because we have no choice but to pass the value as parameters + * we need 64bit to hold 64bit memory address, thus changing + * to uint64_t instead of long in win x64 + * @author - fadedreamz@gmail.com + */ +int32_t iguana_scriptdata(struct iguana_info *coin,uint8_t *scriptspace,uint64_t fileptr[2],char *fname,uint64_t scriptpos,int32_t scriptlen) +#else +int32_t iguana_scriptdata(struct iguana_info *coin, uint8_t *scriptspace, long fileptr[2], char *fname, uint64_t scriptpos, int32_t scriptlen) +#endif { FILE *fp; long err; int32_t retval = scriptlen; #ifndef __PNACL__ if ( scriptpos < 0xffffffff ) { if ( fileptr[0] == 0 ) - fileptr[0] = (long)OS_mapfile(fname,&fileptr[1],0); +#if defined(_M_X64) + fileptr[0] = (uint64_t)OS_mapfile(fname,&fileptr[1],0); +#else + fileptr[0] = (long)OS_mapfile(fname, &fileptr[1], 0); +#endif if ( fileptr[0] != 0 ) { if ( (scriptpos + scriptlen) <= fileptr[1] ) @@ -249,7 +263,17 @@ int32_t iguana_ramtxbytes(struct iguana_info *coin,uint8_t *serialized,int32_t m int32_t iguana_peerblockrequest(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *blockspace,int32_t max,struct iguana_peer *addr,bits256 hash2,int32_t validatesigs) { +#if defined(_M_X64) + /* + * because we have no choice but to access the memory address + * we need 64bit to correctly hold 64bit memory address, thus changing + * to uint64_t instead of long in win x64 + * @author - fadedreamz@gmail.com + */ + struct iguana_txid *tx, T; bits256 checktxid; int32_t i, len, total, bundlei = -2; struct iguana_block *block; struct iguana_msgzblock zmsgB; bits256 *tree, checkhash2, merkle_root; struct iguana_bundle *bp = 0; uint64_t tmp; char str[65]; struct iguana_ramchaindata *rdata; +#else struct iguana_txid *tx,T; bits256 checktxid; int32_t i,len,total,bundlei=-2; struct iguana_block *block; struct iguana_msgzblock zmsgB; bits256 *tree,checkhash2,merkle_root; struct iguana_bundle *bp=0; long tmp; char str[65]; struct iguana_ramchaindata *rdata; +#endif if ( (bp= iguana_bundlefind(coin,&bp,&bundlei,hash2)) != 0 && bundlei >= 0 && bundlei < bp->n ) { if ( (rdata= bp->ramchain.H.data) == 0 )//&& bp == coin->current ) @@ -298,7 +322,17 @@ int32_t iguana_peerblockrequest(struct supernet_info *myinfo,struct iguana_info } if ( i == block->RO.txn_count ) { +#if defined(_M_X64) + /* + * because we have no choice but to access the memory address + * we need 64bit to correctly hold 64bit memory address, thus changing + * to uint64_t instead of long in win x64 + * @author - fadedreamz@gmail.com + */ + tmp = (uint64_t)&blockspace[sizeof(struct iguana_msghdr) + total + sizeof(bits256)]; +#else tmp = (long)&blockspace[sizeof(struct iguana_msghdr) + total + sizeof(bits256)]; +#endif tmp &= ~(sizeof(bits256) - 1); tree = (void *)tmp; for (i=0; iRO.txn_count; i++) diff --git a/iguana/iguana_txidfind.c b/iguana/iguana_txidfind.c index d8cec460f..cf49872ef 100755 --- a/iguana/iguana_txidfind.c +++ b/iguana/iguana_txidfind.c @@ -193,7 +193,17 @@ uint32_t iguana_sparseadd(uint8_t *bits,uint32_t ind,int32_t width,uint32_t tabl // ramchain->sparsemax = i; return(setind); } + // fadedreamz@gmail.com +#if defined(_M_X64) + /* + * calculate the address in a portable manner + * in all platform sizeof(char) / sizeof(uchar) == 1 + * @author - fadedreamz@gmail.com + */ + else if (x < maxitems && memcmp((void *)((unsigned char *)refdata + x*refsize), key, keylen) == 0) +#else else if ( x < maxitems && memcmp((void *)(long)((long)refdata + x*refsize),key,keylen) == 0 ) +#endif { if ( setind == 0 ) ramchain->sparsehits++; diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 10a2de86b..a90ca45b8 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -580,7 +580,16 @@ struct iguana_peer *iguana_peerfindipbits(struct iguana_info *coin,uint32_t ipbi //int32_t basilisk_relays_send(struct supernet_info *myinfo,struct iguana_peer *addr); int32_t basilisk_hashes_send(struct supernet_info *myinfo,struct iguana_info *virt,struct iguana_peer *addr,char *CMD,bits256 *txids,int32_t num); int32_t iguana_opreturn(struct supernet_info *myinfo,int32_t ordered,struct iguana_info *coin,uint32_t timestamp,struct iguana_bundle *bp,int64_t crypto777_payment,int32_t height,uint64_t hdrsi_unspentind,int64_t payment,uint32_t fileid,uint64_t scriptpos,uint32_t scriptlen); +/* +* because the address passed in a non-portable way we defined uint64_t as parameter to +* allow the pass of 64bit memory address in windows 64 +* @author - fadedreamz@gmail.com +*/ +#if defined(_M_X64) +int32_t iguana_scriptdata(struct iguana_info *coin, uint8_t *scriptspace, uint64_t fileptr[2], char *fname, uint64_t scriptpos, int32_t scriptlen); +#else int32_t iguana_scriptdata(struct iguana_info *coin,uint8_t *scriptspace,long fileptr[2],char *fname,uint64_t scriptpos,int32_t scriptlen); +#endif void basilisk_ensurerelay(struct supernet_info *myinfo,struct iguana_info *notaries,uint32_t ipbits); void dpow_nanomsginit(struct supernet_info *myinfo,char *ipaddr); int32_t iguana_datachain_scan(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t rmd160[20]); diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index 5ba718576..c2a9f86cd 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -301,7 +301,17 @@ struct iguana_txblock struct iguana_zblock zblock; }; +#if defined(_M_X64) +/* +* calculate the address in a portable manner +* in all platform sizeof(char) / sizeof(uchar) == 1 +* @author - fadedreamz@gmail.com +*/ +#define RAMCHAIN_PTR(rdata,offset) ((void *)((unsigned char *)rdata + rdata->offset)) +#else #define RAMCHAIN_PTR(rdata,offset) ((void *)(long)((long)(rdata) + (long)(rdata)->offset)) +#endif + struct iguana_ramchaindata { bits256 sha256; @@ -461,7 +471,17 @@ struct iguana_info struct iguana_peers *peers; struct iguana_peer internaladdr; //basilisk_func basilisk_rawtx,basilisk_balances,basilisk_value; //basilisk_metricfunc basilisk_rawtxmetric,basilisk_balancesmetric,basilisk_valuemetric; +#if defined(_M_X64) + /* + * because we have no choice but to pass the value as parameters + * we need 64bit to hold 64bit memory address, thus changing + * to uint64_t instead of long in win x64 + * @author - fadedreamz@gmail.com + */ + uint64_t vinptrs[IGUANA_MAXPEERS + 1][2], voutptrs[IGUANA_MAXPEERS + 1][2]; +#else long vinptrs[IGUANA_MAXPEERS+1][2],voutptrs[IGUANA_MAXPEERS+1][2]; +#endif uint32_t fastfind; FILE *fastfps[0x100]; uint8_t *fast[0x100]; int32_t *fasttables[0x100]; long fastsizes[0x100]; uint64_t instance_nonce,myservices,totalsize,totalrecv,totalpackets,sleeptime; int64_t mining,totalfees,TMPallocated,MAXRECVCACHE,MAXMEM,PREFETCHLAG,estsize,activebundles;