Browse Source

Avoid aliasing problems by using special buf endian handling functions wrapping memcpy

pull/122/head
Francisco Blas (klondike) Izquierdo Riera 10 years ago
parent
commit
1636187e26
  1. 2
      Destination.cpp
  2. 8
      Garlic.cpp
  3. 2
      I2PEndian.cpp
  4. 25
      I2PEndian.h
  5. 4
      Identity.cpp
  6. 4
      NTCPSession.cpp
  7. 6
      NetDb.cpp
  8. 8
      SSUData.cpp
  9. 23
      SSUSession.cpp
  10. 2
      Streaming.cpp
  11. 14
      Streaming.h
  12. 2
      Tunnel.cpp
  13. 8
      TunnelEndpoint.cpp

2
Destination.cpp

@ -357,7 +357,7 @@ namespace client @@ -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])

8
Garlic.cpp

@ -331,7 +331,7 @@ namespace garlic @@ -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 @@ -389,7 +389,7 @@ namespace garlic
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<i2p::crypto::CBCDecryption> 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 @@ -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 @@ -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 ())

2
I2PEndian.cpp

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include "LittleBigEndian.h"
#ifdef NEEDS_LOCAL_ENDIAN
uint16_t htobe16(uint16_t int16)
{
BigEndian<uint16_t> u16(int16);
@ -40,6 +41,7 @@ uint64_t be64toh(uint64_t big64) @@ -40,6 +41,7 @@ uint64_t be64toh(uint64_t big64)
LittleEndian<uint64_t> u64(big64);
return u64.raw_value;
}
#endif
/* it can be used in Windows 8
#include <Winsock2.h>

25
I2PEndian.h

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
#ifndef I2PENDIAN_H__
#define I2PENDIAN_H__
#include <inttypes.h>
#include <cstring>
#if defined(__linux__) || defined(__FreeBSD_kernel__)
#include <endian.h>
@ -25,6 +27,7 @@ @@ -25,6 +27,7 @@
#define le64toh(x) OSSwapLittleToHostInt64(x)
#else
#define NEEDS_LOCAL_ENDIAN
#include <cstdint>
uint16_t htobe16(uint16_t int16);
uint32_t htobe32(uint32_t int32);
@ -44,5 +47,27 @@ uint64_t be64toh(uint64_t big64); @@ -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__

4
Identity.cpp

@ -275,14 +275,14 @@ namespace data @@ -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;
}

4
NTCPSession.cpp

@ -338,7 +338,7 @@ namespace transport @@ -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 @@ -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

6
NetDb.cpp

@ -436,7 +436,7 @@ namespace data @@ -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 @@ -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)
{

8
SSUData.cpp

@ -84,7 +84,7 @@ namespace transport @@ -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 @@ -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 @@ -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

23
SSUSession.cpp

@ -210,7 +210,7 @@ namespace transport @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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

2
Streaming.cpp

@ -167,7 +167,7 @@ namespace stream @@ -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;
}

14
Streaming.h

@ -53,15 +53,15 @@ namespace stream @@ -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 (); };

2
Tunnel.cpp

@ -356,7 +356,7 @@ namespace tunnel @@ -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);

8
TunnelEndpoint.cpp

@ -61,7 +61,7 @@ namespace tunnel @@ -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 @@ -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 @@ -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);

Loading…
Cancel
Save