From c7b22d466f6bdc4a470f19f711afd131a4df4ab4 Mon Sep 17 00:00:00 2001 From: Eric House Date: Fri, 28 Jun 2019 21:22:45 -0700 Subject: [PATCH] debug-build-only macros to find proto-based crashes When a stream reader and writer are out of sync it often shows up as trying to read off the end of the stream (firing an assert.) It's useful to know where that's coming from on android where there's usually no stack trace in the jin world. So pass __func__ in using macros, and log before asserting. Crude but quick and already useful. --- xwords4/common/memstream.c | 26 +++++++++++++++++++------- xwords4/common/xwstream.h | 30 ++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/xwords4/common/memstream.c b/xwords4/common/memstream.c index f7cd5f53b..399e0978c 100644 --- a/xwords4/common/memstream.c +++ b/xwords4/common/memstream.c @@ -113,7 +113,7 @@ mem_stream_make_sized( MPFORMAL VTableMgr* vtmgr, XP_U16 startSize, } static void -mem_stream_getBytes( XWStreamCtxt* p_sctx, void* where, XP_U16 count ) +mem_stream_getBytes( DBG_PROC_FORMAL XWStreamCtxt* p_sctx, void* where, XP_U16 count ) { MemStreamCtxt* stream = (MemStreamCtxt*)p_sctx; @@ -121,8 +121,20 @@ mem_stream_getBytes( XWStreamCtxt* p_sctx, void* where, XP_U16 count ) stream->nReadBits = 0; } +#ifdef MEM_DEBUG + if( stream->curReadPos + count > stream->nBytesAllocated ) { + XP_LOGF( "%s(): caller: %s()", __func__, DBG_PROC_VAL_NOCOMMA ); + XP_ASSERT(0); + } + if ( stream->curReadPos + count > stream->nBytesWritten ) { + XP_LOGF( "%s(): caller: %s()", __func__, DBG_PROC_VAL_NOCOMMA ); + XP_ASSERT(0); + } +#else XP_ASSERT( stream->curReadPos + count <= stream->nBytesAllocated ); XP_ASSERT( stream->curReadPos + count <= stream->nBytesWritten ); +#endif + XP_MEMCPY( where, stream->buf + stream->curReadPos, count ); stream->curReadPos += count; @@ -130,27 +142,27 @@ mem_stream_getBytes( XWStreamCtxt* p_sctx, void* where, XP_U16 count ) } /* mem_stream_getBytes */ static XP_U8 -mem_stream_getU8( XWStreamCtxt* p_sctx ) +mem_stream_getU8( DBG_PROC_FORMAL XWStreamCtxt* p_sctx ) { XP_U8 result; - mem_stream_getBytes( p_sctx, &result, sizeof(result) ); + mem_stream_getBytes( DBG_PROC_VAL p_sctx, &result, sizeof(result) ); return result; } /* mem_stream_getU8 */ static XP_U16 -mem_stream_getU16( XWStreamCtxt* p_sctx ) +mem_stream_getU16( DBG_PROC_FORMAL XWStreamCtxt* p_sctx ) { XP_U16 result; - mem_stream_getBytes( p_sctx, &result, sizeof(result) ); + mem_stream_getBytes( DBG_PROC_VAL p_sctx, &result, sizeof(result) ); return XP_NTOHS(result); } /* mem_stream_getU16 */ static XP_U32 -mem_stream_getU32( XWStreamCtxt* p_sctx ) +mem_stream_getU32( DBG_PROC_FORMAL XWStreamCtxt* p_sctx ) { XP_U32 result; - mem_stream_getBytes( p_sctx, &result, sizeof(result) ); + mem_stream_getBytes( DBG_PROC_VAL p_sctx, &result, sizeof(result) ); return XP_NTOHL( result ); } /* mem_stream_getU32 */ diff --git a/xwords4/common/xwstream.h b/xwords4/common/xwstream.h index a9177e644..a6a2efb66 100644 --- a/xwords4/common/xwstream.h +++ b/xwords4/common/xwstream.h @@ -40,14 +40,28 @@ typedef XP_U8 PosWhich; # define DBG_LINE_FILE_PARM #endif + +#ifdef MEM_DEBUG +# define DBG_PROC __func__, +# define DBG_PROC_FORMAL const char* proc, +# define DBG_PROC_VAL_NOCOMMA proc +# define DBG_PROC_VAL DBG_PROC_VAL_NOCOMMA, +#else +# define DBG_PROC +# define DBG_PROC_FORMAL +# define DBG_PROC_VAL_NOCOMMA +# define DBG_PROC_VAL +#endif + + typedef struct StreamCtxVTable { void (*m_stream_destroy)( XWStreamCtxt* dctx ); - XP_U8 (*m_stream_getU8)( XWStreamCtxt* dctx ); - void (*m_stream_getBytes)( XWStreamCtxt* dctx, void* where, + XP_U8 (*m_stream_getU8)( DBG_PROC_FORMAL XWStreamCtxt* dctx ); + void (*m_stream_getBytes)( DBG_PROC_FORMAL XWStreamCtxt* dctx, void* where, XP_U16 count ); - XP_U16 (*m_stream_getU16)( XWStreamCtxt* dctx ); - XP_U32 (*m_stream_getU32)( XWStreamCtxt* dctx ); + XP_U16 (*m_stream_getU16)( DBG_PROC_FORMAL XWStreamCtxt* dctx ); + XP_U32 (*m_stream_getU32)( DBG_PROC_FORMAL XWStreamCtxt* dctx ); XP_U32 (*m_stream_getBits)( XWStreamCtxt* dctx, XP_U16 nBits ); #if defined DEBUG void (*m_stream_copyBits)( const XWStreamCtxt* dctx, XWStreamPos endPos, @@ -102,16 +116,16 @@ struct XWStreamCtxt { (sc)->vtable->m_stream_destroy(sc) #define stream_getU8(sc) \ - (sc)->vtable->m_stream_getU8(sc) + (sc)->vtable->m_stream_getU8(DBG_PROC (sc)) #define stream_getBytes(sc, wh, c ) \ - (sc)->vtable->m_stream_getBytes((sc), (wh), (c)) + (sc)->vtable->m_stream_getBytes(DBG_PROC (sc), (wh), (c)) #define stream_getU16(sc) \ - (sc)->vtable->m_stream_getU16(sc) + (sc)->vtable->m_stream_getU16(DBG_PROC sc) #define stream_getU32(sc) \ - (sc)->vtable->m_stream_getU32(sc) + (sc)->vtable->m_stream_getU32(DBG_PROC sc) #define stream_getBits(sc, n) \ (sc)->vtable->m_stream_getBits((sc), (n))