From c438a59b0e5695d547e2ca90ff5d5564a87f0977 Mon Sep 17 00:00:00 2001 From: dmaclach Date: Thu, 19 Sep 2019 17:44:52 -0700 Subject: [PATCH] Remove OSReadLittle* due to alignment requirements The OSReadLittleInt64 function as defined by Apple reduces down to: `return *(volatile uint64_t *)((uintptr_t)base + byteOffset);` which means we are type-punning using a cast. On ARMv7 and other aligned architectures this can cause crashes. Minimal example: https://gist.github.com/dmaclach/b10b0a71ae614d304c067cb9bd264336 --- objectivec/GPBCodedInputStream.m | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m index 57d04dde3830..4c8d640fda66 100644 --- a/objectivec/GPBCodedInputStream.m +++ b/objectivec/GPBCodedInputStream.m @@ -93,14 +93,22 @@ static int8_t ReadRawByte(GPBCodedInputStreamState *state) { static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int32_t)); - int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); + // Not using OSReadLittleInt32 because it has undocumented dependency + // on reads being aligned. + int32_t value; + memcpy(&value, state->bytes + state->bufferPos, sizeof(int32_t)); + value = OSSwapLittleToHostInt32(value); state->bufferPos += sizeof(int32_t); return value; } static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int64_t)); - int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); + // Not using OSReadLittleInt64 because it has undocumented dependency + // on reads being aligned. + int64_t value; + memcpy(&value, state->bytes + state->bufferPos, sizeof(int64_t)); + value = OSSwapLittleToHostInt64(value); state->bufferPos += sizeof(int64_t); return value; }