From 1636187e2650d0fa49fe6c8ef0e9157ba8437484 Mon Sep 17 00:00:00 2001 From: "Francisco Blas (klondike) Izquierdo Riera" Date: Mon, 29 Dec 2014 23:04:02 +0100 Subject: [PATCH] Avoid aliasing problems by using special buf endian handling functions wrapping memcpy --- Destination.cpp | 2 +- Garlic.cpp | 8 ++++---- I2PEndian.cpp | 2 ++ I2PEndian.h | 25 +++++++++++++++++++++++++ Identity.cpp | 4 ++-- NTCPSession.cpp | 4 ++-- NetDb.cpp | 6 +++--- SSUData.cpp | 8 ++++---- SSUSession.cpp | 23 ++++++++++++----------- Streaming.cpp | 2 +- Streaming.h | 14 +++++++------- Tunnel.cpp | 2 +- TunnelEndpoint.cpp | 8 ++++---- 13 files changed, 68 insertions(+), 40 deletions(-) diff --git a/Destination.cpp b/Destination.cpp index b3102206..8c8f5072 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -357,7 +357,7 @@ namespace client void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { - uint32_t length = be32toh (*(uint32_t *)buf); + uint32_t length = bufbe32toh (buf); buf += 4; // we assume I2CP payload switch (buf[9]) diff --git a/Garlic.cpp b/Garlic.cpp index f60c5c49..62fd010f 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -331,7 +331,7 @@ namespace garlic void GarlicDestination::HandleGarlicMessage (I2NPMessage * msg) { uint8_t * buf = msg->GetPayload (); - uint32_t length = be32toh (*(uint32_t *)buf); + uint32_t length = bufbe32toh (buf); buf += 4; // length auto it = m_Tags.find (SessionTag(buf)); if (it != m_Tags.end ()) @@ -389,7 +389,7 @@ namespace garlic void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, i2p::tunnel::InboundTunnel * from) { - uint16_t tagCount = be16toh (*(uint16_t *)buf); + uint16_t tagCount = bufbe16toh (buf); buf += 2; len -= 2; if (tagCount > 0) { @@ -404,7 +404,7 @@ namespace garlic } buf += tagCount*32; len -= tagCount*32; - uint32_t payloadSize = be32toh (*(uint32_t *)buf); + uint32_t payloadSize = bufbe32toh (buf); if (payloadSize > len) { LogPrint (eLogError, "Unexpected payload size ", payloadSize); @@ -460,7 +460,7 @@ namespace garlic // gwHash and gwTunnel sequence is reverted uint8_t * gwHash = buf; buf += 32; - uint32_t gwTunnel = be32toh (*(uint32_t *)buf); + uint32_t gwTunnel = bufbe32toh (buf); buf += 4; i2p::tunnel::OutboundTunnel * tunnel = nullptr; if (from && from->GetTunnelPool ()) diff --git a/I2PEndian.cpp b/I2PEndian.cpp index 1fccf47f..b8a041d8 100644 --- a/I2PEndian.cpp +++ b/I2PEndian.cpp @@ -5,6 +5,7 @@ #include "LittleBigEndian.h" +#ifdef NEEDS_LOCAL_ENDIAN uint16_t htobe16(uint16_t int16) { BigEndian u16(int16); @@ -40,6 +41,7 @@ uint64_t be64toh(uint64_t big64) LittleEndian u64(big64); return u64.raw_value; } +#endif /* it can be used in Windows 8 #include diff --git a/I2PEndian.h b/I2PEndian.h index f7a2a95f..cff68669 100644 --- a/I2PEndian.h +++ b/I2PEndian.h @@ -1,5 +1,7 @@ #ifndef I2PENDIAN_H__ #define I2PENDIAN_H__ +#include +#include #if defined(__linux__) || defined(__FreeBSD_kernel__) #include @@ -25,6 +27,7 @@ #define le64toh(x) OSSwapLittleToHostInt64(x) #else +#define NEEDS_LOCAL_ENDIAN #include uint16_t htobe16(uint16_t int16); uint32_t htobe32(uint32_t int32); @@ -44,5 +47,27 @@ uint64_t be64toh(uint64_t big64); #endif +inline uint16_t bufbe16toh(const uint8_t *buf) +{ + uint16_t big16; + memcpy(&big16, buf, sizeof(uint16_t)); + return be16toh(big16); +} + +inline uint32_t bufbe32toh(const uint8_t *buf) +{ + uint32_t big32; + memcpy(&big32, buf, sizeof(uint32_t)); + return be32toh(big32); +} + +inline uint64_t bufbe64toh(const uint8_t *buf) +{ + uint64_t big64; + memcpy(&big64, buf, sizeof(uint64_t)); + return be64toh(big64); +} + + #endif // I2PENDIAN_H__ diff --git a/Identity.cpp b/Identity.cpp index 7b081185..e7d9afcb 100644 --- a/Identity.cpp +++ b/Identity.cpp @@ -275,14 +275,14 @@ namespace data SigningKeyType IdentityEx::GetSigningKeyType () const { if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer) - return be16toh (*(const uint16_t *)m_ExtendedBuffer); // signing key + return bufbe16toh (m_ExtendedBuffer); // signing key return SIGNING_KEY_TYPE_DSA_SHA1; } CryptoKeyType IdentityEx::GetCryptoKeyType () const { if (m_StandardIdentity.certificate.type == CERTIFICATE_TYPE_KEY && m_ExtendedBuffer) - return be16toh (*(const uint16_t *)(m_ExtendedBuffer + 2)); // crypto key + return bufbe16toh (m_ExtendedBuffer + 2); // crypto key return CRYPTO_KEY_TYPE_ELGAMAL; } diff --git a/NTCPSession.cpp b/NTCPSession.cpp index 42cbd5ba..f16264f4 100644 --- a/NTCPSession.cpp +++ b/NTCPSession.cpp @@ -338,7 +338,7 @@ namespace transport LogPrint (eLogDebug, "Phase 3 received: ", bytes_transferred); m_Decryption.Decrypt (m_ReceiveBuffer, bytes_transferred, m_ReceiveBuffer); uint8_t * buf = m_ReceiveBuffer; - uint16_t size = be16toh (*(uint16_t *)buf); + uint16_t size = bufbe16toh (buf); m_RemoteIdentity.FromBuffer (buf + 2, size); size_t expectedSize = size + 2/*size*/ + 4/*timestamp*/ + m_RemoteIdentity.GetSignatureLen (); size_t paddingLen = expectedSize & 0x0F; @@ -526,7 +526,7 @@ namespace transport m_NextMessageOffset = 0; m_Decryption.Decrypt (encrypted, m_NextMessage->buf); - uint16_t dataSize = be16toh (*(uint16_t *)m_NextMessage->buf); + uint16_t dataSize = bufbe16toh (m_NextMessage->buf); if (dataSize) { // new message diff --git a/NetDb.cpp b/NetDb.cpp index c621b4e5..9cd7a924 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -436,7 +436,7 @@ namespace data else { LogPrint ("RouterInfo"); - size_t size = be16toh (*(uint16_t *)(buf + offset)); + size_t size = bufbe16toh (buf + offset); if (size > 2048) { LogPrint ("Invalid RouterInfo length ", (int)size); @@ -597,10 +597,10 @@ namespace data uint32_t replyTunnelID = 0; if (flag & 0x01) //reply to tunnel { - replyTunnelID = be32toh (*(uint32_t *)(buf + 64)); + replyTunnelID = bufbe32toh (buf + 64); excluded += 4; } - uint16_t numExcluded = be16toh (*(uint16_t *)excluded); + uint16_t numExcluded = bufbe16toh (excluded); excluded += 2; if (numExcluded > 512) { diff --git a/SSUData.cpp b/SSUData.cpp index fbc581a6..596b7238 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -84,7 +84,7 @@ namespace transport uint8_t numAcks =*buf; buf++; for (int i = 0; i < numAcks; i++) - ProcessSentMessageAck (be32toh (((uint32_t *)buf)[i])); + ProcessSentMessageAck (bufbe32toh (buf+i*4)); buf += numAcks*4; } if (flag & DATA_FLAG_ACK_BITFIELDS_INCLUDED) @@ -94,7 +94,7 @@ namespace transport buf++; for (int i = 0; i < numBitfields; i++) { - uint32_t msgID = be32toh (*(uint32_t *)buf); + uint32_t msgID = bufbe32toh (buf); buf += 4; // msgID auto it = m_SentMessages.find (msgID); // process individual Ack bitfields @@ -137,13 +137,13 @@ namespace transport buf++; for (int i = 0; i < numFragments; i++) { - uint32_t msgID = be32toh (*(uint32_t *)buf); // message ID + uint32_t msgID = bufbe32toh (buf); // message ID buf += 4; uint8_t frag[4]; frag[0] = 0; memcpy (frag + 1, buf, 3); buf += 3; - uint32_t fragmentInfo = be32toh (*(uint32_t *)frag); // fragment info + uint32_t fragmentInfo = bufbe32toh (frag); // fragment info uint16_t fragmentSize = fragmentInfo & 0x1FFF; // bits 0 - 13 bool isLast = fragmentInfo & 0x010000; // bit 16 uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 diff --git a/SSUSession.cpp b/SSUSession.cpp index e451021a..fffc232d 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -210,7 +210,7 @@ namespace transport } s.Insert (ourAddress, addressSize); // our IP payload += addressSize; // address - uint16_t ourPort = be16toh (*(uint16_t *)payload); + uint16_t ourPort = bufbe16toh (payload); s.Insert (payload, 2); // our port payload += 2; // port LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); @@ -221,7 +221,7 @@ namespace transport s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP v6 s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port s.Insert (payload, 8); // relayTag and signed on time - m_RelayTag = be32toh (*(uint32_t *)payload); + m_RelayTag = bufbe32toh (payload); payload += 4; // relayTag payload += 4; // signed on time // decrypt signature @@ -242,7 +242,7 @@ namespace transport LogPrint (eLogDebug, "Session confirmed received"); uint8_t * payload = buf + sizeof (SSUHeader); payload++; // identity fragment info - uint16_t identitySize = be16toh (*(uint16_t *)payload); + uint16_t identitySize = bufbe16toh (payload); payload += 2; // size of identity fragment m_RemoteIdentity.FromBuffer (payload, identitySize); m_Data.UpdatePacketSize (m_RemoteIdentity.GetIdentHash ()); @@ -443,7 +443,7 @@ namespace transport void SSUSession::ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from) { - uint32_t relayTag = be32toh (*(uint32_t *)buf); + uint32_t relayTag = bufbe32toh (buf); auto session = m_Server.FindRelaySession (relayTag); if (session) { @@ -457,7 +457,7 @@ namespace transport buf += challengeSize; uint8_t * introKey = buf; buf += 32; // introkey - uint32_t nonce = be32toh (*(uint32_t *)buf); + uint32_t nonce = bufbe32toh (buf); SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint); SendRelayIntro (session.get (), from); } @@ -550,9 +550,9 @@ namespace transport uint8_t * payload = buf + sizeof (SSUHeader); uint8_t remoteSize = *payload; payload++; // remote size - //boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload))); + //boost::asio::ip::address_v4 remoteIP (bufbe32toh (payload)); payload += remoteSize; // remote address - //uint16_t remotePort = be16toh (*(uint16_t *)(payload)); + //uint16_t remotePort = bufbe16toh (payload); payload += 2; // remote port uint8_t ourSize = *payload; payload++; // our size @@ -570,7 +570,7 @@ namespace transport ourIP = boost::asio::ip::address_v6 (bytes); } payload += ourSize; // our address - uint16_t ourPort = be16toh (*(uint16_t *)(payload)); + uint16_t ourPort = bufbe16toh (payload); payload += 2; // our port LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort); i2p::context.UpdateAddress (ourIP); @@ -582,9 +582,9 @@ namespace transport if (size == 4) { buf++; // size - boost::asio::ip::address_v4 address (be32toh (*(uint32_t* )buf)); + boost::asio::ip::address_v4 address (bufbe32toh (buf)); buf += 4; // address - uint16_t port = be16toh (*(uint16_t *)buf); + uint16_t port = bufbe16toh (buf); // send hole punch of 1 byte m_Server.Send (buf, 0, boost::asio::ip::udp::endpoint (address, port)); } @@ -844,10 +844,11 @@ namespace transport void SSUSession::ProcessPeerTest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { uint8_t * buf1 = buf; - uint32_t nonce = be32toh (*(uint32_t *)buf); + uint32_t nonce = bufbe32toh (buf); buf += 4; // nonce uint8_t size = *buf; buf++; // size + uint32_t address = (size == 4) ? *(uint32_t *)buf : 0; // use it as is buf += size; // address uint16_t port = *(uint16_t *)buf; // use it as is diff --git a/Streaming.cpp b/Streaming.cpp index bad57687..fa353275 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -167,7 +167,7 @@ namespace stream if (flags & PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED) { - uint16_t maxPacketSize = be16toh (*(uint16_t *)optionData); + uint16_t maxPacketSize = bufbe16toh (optionData); LogPrint (eLogDebug, "Max packet size ", maxPacketSize); optionData += 2; } diff --git a/Streaming.h b/Streaming.h index b2015f08..69ef124d 100644 --- a/Streaming.h +++ b/Streaming.h @@ -53,15 +53,15 @@ namespace stream uint8_t * GetBuffer () { return buf + offset; }; size_t GetLength () const { return len - offset; }; - uint32_t GetSendStreamID () const { return be32toh (*(uint32_t *)buf); }; - uint32_t GetReceiveStreamID () const { return be32toh (*(uint32_t *)(buf + 4)); }; - uint32_t GetSeqn () const { return be32toh (*(uint32_t *)(buf + 8)); }; - uint32_t GetAckThrough () const { return be32toh (*(uint32_t *)(buf + 12)); }; + uint32_t GetSendStreamID () const { return bufbe32toh (buf); }; + uint32_t GetReceiveStreamID () const { return bufbe32toh (buf + 4); }; + uint32_t GetSeqn () const { return bufbe32toh (buf + 8); }; + uint32_t GetAckThrough () const { return bufbe32toh (buf + 12); }; uint8_t GetNACKCount () const { return buf[16]; }; - uint32_t GetNACK (int i) const { return be32toh (((uint32_t *)(buf + 17))[i]); }; + uint32_t GetNACK (int i) const { return bufbe32toh (buf + 17 + 4 * i); }; const uint8_t * GetOption () const { return buf + 17 + GetNACKCount ()*4 + 3; }; // 3 = resendDelay + flags - uint16_t GetFlags () const { return be16toh (*(uint16_t *)(GetOption () - 2)); }; - uint16_t GetOptionSize () const { return be16toh (*(uint16_t *)GetOption ()); }; + uint16_t GetFlags () const { return bufbe16toh (GetOption () - 2); }; + uint16_t GetOptionSize () const { return bufbe16toh (GetOption ()); }; const uint8_t * GetOptionData () const { return GetOption () + 2; }; const uint8_t * GetPayload () const { return GetOptionData () + GetOptionSize (); }; diff --git a/Tunnel.cpp b/Tunnel.cpp index b61551d1..a1a8387a 100644 --- a/Tunnel.cpp +++ b/Tunnel.cpp @@ -356,7 +356,7 @@ namespace tunnel I2NPMessage * msg = m_Queue.GetNextWithTimeout (1000); // 1 sec while (msg) { - uint32_t tunnelID = be32toh (*(uint32_t *)msg->GetPayload ()); + uint32_t tunnelID = bufbe32toh (msg->GetPayload ()); InboundTunnel * tunnel = GetInboundTunnel (tunnelID); if (tunnel) tunnel->HandleTunnelDataMsg (msg); diff --git a/TunnelEndpoint.cpp b/TunnelEndpoint.cpp index 6074254e..6f28b990 100644 --- a/TunnelEndpoint.cpp +++ b/TunnelEndpoint.cpp @@ -61,7 +61,7 @@ namespace tunnel break; case eDeliveryTypeTunnel: // 1 LogPrint ("Delivery type tunnel"); - m.tunnelID = be32toh (*(uint32_t *)fragment); + m.tunnelID = bufbe32toh (fragment); fragment += 4; // tunnelID m.hash = i2p::data::IdentHash (fragment); fragment += 32; // hash @@ -79,7 +79,7 @@ namespace tunnel if (isFragmented) { // Message ID - msgID = be32toh (*(uint32_t *)fragment); + msgID = bufbe32toh (fragment); fragment += 4; LogPrint ("Fragmented message ", msgID); isLastFragment = false; @@ -88,14 +88,14 @@ namespace tunnel else { // follow on - msgID = be32toh (*(uint32_t *)fragment); // MessageID + msgID = bufbe32toh (fragment); // MessageID fragment += 4; fragmentNum = (flag >> 1) & 0x3F; // 6 bits isLastFragment = flag & 0x01; LogPrint ("Follow on fragment ", fragmentNum, " of message ", msgID, isLastFragment ? " last" : " non-last"); } - uint16_t size = be16toh (*(uint16_t *)fragment); + uint16_t size = bufbe16toh (fragment); fragment += 2; LogPrint ("Fragment size=", (int)size);