From 136a8998c4441305718f3574a33cbf5e7bfac939 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 21 Nov 2024 18:04:50 +0100 Subject: [PATCH] [winpr,stream] fix 64bit stream function * Fix Stream_Write_UINT64* functions * Add unit tests to cover that --- winpr/include/winpr/stream.h | 46 ++++++-- winpr/libwinpr/utils/test/TestStream.c | 150 +++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 8 deletions(-) diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 4ff0a7058..fb8b7fb09 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -1024,14 +1024,10 @@ extern "C" WINPR_ASSERT(_s->pointer); WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4); - *_s->pointer++ = (_v) & 0xFF; - *_s->pointer++ = ((_v) >> 8) & 0xFF; - *_s->pointer++ = ((_v) >> 16) & 0xFF; *_s->pointer++ = ((_v) >> 24) & 0xFF; - *_s->pointer++ = (_v) & 0xFF; - *_s->pointer++ = ((_v) >> 8) & 0xFF; *_s->pointer++ = ((_v) >> 16) & 0xFF; - *_s->pointer++ = ((_v) >> 24) & 0xFF; + *_s->pointer++ = ((_v) >> 8) & 0xFF; + *_s->pointer++ = (_v) & 0xFF; } #define Stream_Write_UINT32(s, v) \ @@ -1099,7 +1095,7 @@ extern "C" WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8); Stream_Write_UINT32(_s, ((_v) & 0xFFFFFFFFUL)); - Stream_Write_UINT32(_s, ((_v) >> 16 & 0xFFFFFFFFUL)); + Stream_Write_UINT32(_s, ((_v) >> 32 & 0xFFFFFFFFUL)); } /** @brief writes a \b UINT64 as \b big endian to a \b wStream. The stream must be large enough @@ -1114,7 +1110,41 @@ extern "C" WINPR_ASSERT(_s->pointer); WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8); - Stream_Write_UINT32_BE(_s, ((_v) >> 16 & 0xFFFFFFFFUL)); + Stream_Write_UINT32_BE(_s, ((_v) >> 32 & 0xFFFFFFFFUL)); + Stream_Write_UINT32_BE(_s, ((_v) & 0xFFFFFFFFUL)); + } + + /** @brief writes a \b INT64 as \b little endian to a \b wStream. The stream must be large + * enough to hold the data. + * + * \param _s The stream to write to, must not be \b NULL + * \param _v The value to write + * \since version 3.10.0 + */ + static INLINE void Stream_Write_INT64(wStream* _s, INT64 _v) + { + WINPR_ASSERT(_s); + WINPR_ASSERT(_s->pointer); + WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8); + + Stream_Write_UINT32(_s, ((_v) & 0xFFFFFFFFUL)); + Stream_Write_UINT32(_s, ((_v) >> 32 & 0xFFFFFFFFUL)); + } + + /** @brief writes a \b INT64 as \b big endian to a \b wStream. The stream must be large enough + * to hold the data. + * + * \param _s The stream to write to, must not be \b NULL + * \param _v The value to write + * \since version 3.10.0 + */ + static INLINE void Stream_Write_INT64_BE(wStream* _s, INT64 _v) + { + WINPR_ASSERT(_s); + WINPR_ASSERT(_s->pointer); + WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8); + + Stream_Write_UINT32_BE(_s, ((_v) >> 32 & 0xFFFFFFFFUL)); Stream_Write_UINT32_BE(_s, ((_v) & 0xFFFFFFFFUL)); } diff --git a/winpr/libwinpr/utils/test/TestStream.c b/winpr/libwinpr/utils/test/TestStream.c index da54fa962..34fd6fe5b 100644 --- a/winpr/libwinpr/utils/test/TestStream.c +++ b/winpr/libwinpr/utils/test/TestStream.c @@ -1,5 +1,6 @@ #include #include +#include #include static BOOL TestStream_Verify(wStream* s, size_t mincap, size_t len, size_t pos) @@ -317,6 +318,145 @@ fail: /* printf("a: 0x%016llX\n", a); */ \ } while (0) +static BOOL TestStream_WriteAndRead(UINT64 value) +{ + union + { + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + INT8 i8; + INT16 i16; + INT32 i32; + INT64 i64; + } val; + val.u64 = value; + + wStream* s = Stream_New(NULL, 1024); + if (!s) + return FALSE; + BOOL rc = FALSE; + + { + Stream_Write_UINT8(s, val.u8); + Stream_Rewind_UINT8(s); + const UINT8 ru8 = Stream_Get_UINT8(s); + Stream_Rewind_UINT8(s); + if (val.u8 != ru8) + goto fail; + } + { + Stream_Write_UINT16(s, val.u16); + Stream_Rewind_UINT16(s); + const UINT16 ru = Stream_Get_UINT16(s); + Stream_Rewind_UINT16(s); + if (val.u16 != ru) + goto fail; + } + { + Stream_Write_UINT16_BE(s, val.u16); + Stream_Rewind_UINT16(s); + const UINT16 ru = Stream_Get_UINT16_BE(s); + Stream_Rewind_UINT16(s); + if (val.u16 != ru) + goto fail; + } + { + Stream_Write_UINT32(s, val.u32); + Stream_Rewind_UINT32(s); + const UINT32 ru = Stream_Get_UINT32(s); + Stream_Rewind_UINT32(s); + if (val.u32 != ru) + goto fail; + } + { + Stream_Write_UINT32_BE(s, val.u32); + Stream_Rewind_UINT32(s); + const UINT32 ru = Stream_Get_UINT32_BE(s); + Stream_Rewind_UINT32(s); + if (val.u32 != ru) + goto fail; + } + { + Stream_Write_UINT64(s, val.u64); + Stream_Rewind_UINT64(s); + const UINT64 ru = Stream_Get_UINT64(s); + Stream_Rewind_UINT64(s); + if (val.u64 != ru) + goto fail; + } + { + Stream_Write_UINT64_BE(s, val.u64); + Stream_Rewind_UINT64(s); + const UINT64 ru = Stream_Get_UINT64_BE(s); + Stream_Rewind_UINT64(s); + if (val.u64 != ru) + goto fail; + } + { + Stream_Write_INT8(s, val.i8); + Stream_Rewind(s, 1); + const INT8 ru8 = Stream_Get_INT8(s); + Stream_Rewind(s, 1); + if (val.i8 != ru8) + goto fail; + } + { + Stream_Write_INT16(s, val.i16); + Stream_Rewind(s, 2); + const INT16 ru = Stream_Get_INT16(s); + Stream_Rewind(s, 2); + if (val.i16 != ru) + goto fail; + } + { + Stream_Write_INT16_BE(s, val.i16); + Stream_Rewind(s, 2); + const INT16 ru = Stream_Get_INT16_BE(s); + Stream_Rewind(s, 2); + if (val.i16 != ru) + goto fail; + } + { + Stream_Write_INT32(s, val.i32); + Stream_Rewind(s, 4); + const INT32 ru = Stream_Get_INT32(s); + Stream_Rewind(s, 4); + if (val.i32 != ru) + goto fail; + } + { + Stream_Write_INT32_BE(s, val.i32); + Stream_Rewind(s, 4); + const INT32 ru = Stream_Get_INT32_BE(s); + Stream_Rewind(s, 4); + if (val.i32 != ru) + goto fail; + } + { + Stream_Write_INT64(s, val.i64); + Stream_Rewind(s, 8); + const INT64 ru = Stream_Get_INT64(s); + Stream_Rewind(s, 8); + if (val.i64 != ru) + goto fail; + } + { + Stream_Write_INT64_BE(s, val.i64); + Stream_Rewind(s, 8); + const INT64 ru = Stream_Get_INT64_BE(s); + Stream_Rewind(s, 8); + if (val.i64 != ru) + goto fail; + } + + rc = TRUE; +fail: + Stream_Free(s, TRUE); + return rc; +} + static BOOL TestStream_Reading(void) { BYTE src[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; @@ -704,5 +844,15 @@ int TestStream(int argc, char* argv[]) if (!TestStream_Static()) return 12; + if (!TestStream_WriteAndRead(0x1234567890abcdef)) + return 13; + + for (size_t x = 0; x < 10; x++) + { + UINT64 val = 0; + winpr_RAND(&val, sizeof(val)); + if (!TestStream_WriteAndRead(val)) + return 14; + } return 0; }