Skip to content

Commit

Permalink
Fix a pointer issue
Browse files Browse the repository at this point in the history
  • Loading branch information
acid-chicken committed Sep 28, 2018
1 parent 11f7e27 commit ce89fde
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 74 deletions.
7 changes: 4 additions & 3 deletions src/addrdb.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -23,8 +24,8 @@ bool SerializeDB(Stream& stream, const Data& data)
// Write and commit header, data
try {
CHashWriter hasher(SER_DISK, CLIENT_VERSION);
stream << FLATDATA(Params().MessageStart()) << data;
hasher << FLATDATA(Params().MessageStart()) << data;
stream << Params().MessageStart() << data;
hasher << Params().MessageStart() << data;
stream << hasher.GetHash();
} catch (const std::exception& e) {
return error("%s: Serialize or I/O error - %s", __func__, e.what());
Expand Down Expand Up @@ -67,7 +68,7 @@ bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
CHashVerifier<Stream> verifier(&stream);
// de-serialize file header (network specific magic number) and ..
unsigned char pchMsgTmp[4];
verifier >> FLATDATA(pchMsgTmp);
verifier >> pchMsgTmp;
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("%s: Invalid network magic number", __func__);
Expand Down
10 changes: 6 additions & 4 deletions src/compressor.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -9,6 +10,7 @@
#include "primitives/transaction.h"
#include "script/script.h"
#include "serialize.h"
#include "span.h"

class CKeyID;
class CPubKey;
Expand Down Expand Up @@ -59,12 +61,12 @@ class CScriptCompressor
void Serialize(Stream &s) const {
std::vector<unsigned char> compr;
if (Compress(compr)) {
s << CFlatData(compr);
s << MakeSpan(compr);
return;
}
unsigned int nSize = script.size() + nSpecialScripts;
s << VARINT(nSize);
s << CFlatData(script);
s << MakeSpan(script);
}

template<typename Stream>
Expand All @@ -73,7 +75,7 @@ class CScriptCompressor
s >> VARINT(nSize);
if (nSize < nSpecialScripts) {
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
s >> REF(CFlatData(vch));
s >> REF(MakeSpan(vch));
Decompress(nSize, vch);
return;
}
Expand All @@ -84,7 +86,7 @@ class CScriptCompressor
s.ignore(nSize);
} else {
script.resize(nSize);
s >> REF(CFlatData(script));
s >> REF(MakeSpan(script));
}
}
};
Expand Down
17 changes: 11 additions & 6 deletions src/netaddress.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -11,6 +12,7 @@

#include "compat.h"
#include "serialize.h"
#include "span.h"

#include <stdint.h>
#include <string>
Expand Down Expand Up @@ -93,7 +95,7 @@ class CNetAddr

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(FLATDATA(ip));
READWRITE(ip);
}

friend class CSubNet;
Expand Down Expand Up @@ -131,8 +133,8 @@ class CSubNet
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(network);
READWRITE(FLATDATA(netmask));
READWRITE(FLATDATA(valid));
READWRITE(netmask);
READWRITE(valid);
}
};

Expand Down Expand Up @@ -166,11 +168,14 @@ class CService : public CNetAddr

template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(FLATDATA(ip));
READWRITE(ip);

// TODO: introduce native support for BE serialization in serialize.h
unsigned short portN = htons(port);
READWRITE(FLATDATA(portN));
if (ser_action.ForRead())
READWRITE(Span<unsigned char>((unsigned char*)&portN, 2));
if (ser_action.ForRead()) {
port = ntohs(portN);
}
}
};

Expand Down
7 changes: 4 additions & 3 deletions src/protocol.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand Down Expand Up @@ -50,10 +51,10 @@ class CMessageHeader
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action)
{
READWRITE(FLATDATA(pchMessageStart));
READWRITE(FLATDATA(pchCommand));
READWRITE(pchMessageStart);
READWRITE(pchCommand);
READWRITE(nMessageSize);
READWRITE(FLATDATA(pchChecksum));
READWRITE(pchChecksum);
}

char pchMessageStart[MESSAGE_START_SIZE];
Expand Down
58 changes: 16 additions & 42 deletions src/serialize.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -22,6 +23,7 @@
#include <vector>

#include "prevector.h"
#include "span.h"

static const unsigned int MAX_SIZE = 0x02000000;

Expand All @@ -41,7 +43,7 @@ constexpr deserialize_type deserialize {};

/**
* Used to bypass the rule against non-const reference to temporary
* where it makes sense with wrappers such as CFlatData or CTxDB
* where it makes sense with wrappers.
*/
template<typename T>
inline T& REF(const T& val)
Expand All @@ -59,6 +61,12 @@ inline T* NCONST_PTR(const T* val)
return const_cast<T*>(val);
}

//! Safely convert odd char pointer types to standard ones.
inline char* CharCast(char* c) { return c; }
inline char* CharCast(unsigned char* c) { return (char*)c; }
inline const char* CharCast(const char* c) { return c; }
inline const char* CharCast(const unsigned char* c) { return (const char*)c; }

/*
* Lowest-level serialization and conversion.
* @note Sizes of these types are verified in the tests
Expand Down Expand Up @@ -178,6 +186,10 @@ template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_wri
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }

template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
Expand All @@ -190,6 +202,9 @@ template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a =
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }

template<typename Stream> inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
template<typename Stream> inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
Expand Down Expand Up @@ -351,51 +366,10 @@ I ReadVarInt(Stream& is)
}
}

#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj)))
#define VARINT(obj) REF(WrapVarInt(REF(obj)))
#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj)))
#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj)))

/**
* Wrapper for serializing arrays and POD.
*/
class CFlatData
{
protected:
char* pbegin;
char* pend;
public:
CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
template <class T, class TAl>
explicit CFlatData(std::vector<T,TAl> &v)
{
pbegin = (char*)v.data();
pend = (char*)(v.data() + v.size());
}
template <unsigned int N, typename T, typename S, typename D>
explicit CFlatData(prevector<N, T, S, D> &v)
{
pbegin = (char*)v.data();
pend = (char*)(v.data() + v.size());
}
char* begin() { return pbegin; }
const char* begin() const { return pbegin; }
char* end() { return pend; }
const char* end() const { return pend; }

template<typename Stream>
void Serialize(Stream& s) const
{
s.write(pbegin, pend - pbegin);
}

template<typename Stream>
void Unserialize(Stream& s)
{
s.read(pbegin, pend - pbegin);
}
};

template<typename I>
class CVarInt
{
Expand Down
62 changes: 62 additions & 0 deletions src/span.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) 2018 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_SPAN_H
#define BITCOIN_SPAN_H

#include <type_traits>
#include <cstddef>
#include <algorithm>

/** A Span is an object that can refer to a contiguous sequence of objects.
*
* It implements a subset of C++20's std::span.
*/
template<typename C>
class Span
{
C* m_data;
std::ptrdiff_t m_size;

public:
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
constexpr Span(C* data, std::ptrdiff_t size) noexcept : m_data(data), m_size(size) {}
constexpr Span(C* data, C* end) noexcept : m_data(data), m_size(end - data) {}

constexpr C* data() const noexcept { return m_data; }
constexpr C* begin() const noexcept { return m_data; }
constexpr C* end() const noexcept { return m_data + m_size; }
constexpr std::ptrdiff_t size() const noexcept { return m_size; }
constexpr C& operator[](std::ptrdiff_t pos) const noexcept { return m_data[pos]; }

constexpr Span<C> subspan(std::ptrdiff_t offset) const noexcept { return Span<C>(m_data + offset, m_size - offset); }
constexpr Span<C> subspan(std::ptrdiff_t offset, std::ptrdiff_t count) const noexcept { return Span<C>(m_data + offset, count); }
constexpr Span<C> first(std::ptrdiff_t count) const noexcept { return Span<C>(m_data, count); }
constexpr Span<C> last(std::ptrdiff_t count) const noexcept { return Span<C>(m_data + m_size - count, count); }

friend constexpr bool operator==(const Span& a, const Span& b) noexcept { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
friend constexpr bool operator!=(const Span& a, const Span& b) noexcept { return !(a == b); }
friend constexpr bool operator<(const Span& a, const Span& b) noexcept { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
friend constexpr bool operator<=(const Span& a, const Span& b) noexcept { return !(b < a); }
friend constexpr bool operator>(const Span& a, const Span& b) noexcept { return (b < a); }
friend constexpr bool operator>=(const Span& a, const Span& b) noexcept { return !(a < b); }
};

/** Create a span to a container exposing data() and size().
*
* This correctly deals with constness: the returned Span's element type will be
* whatever data() returns a pointer to. If either the passed container is const,
* or its element type is const, the resulting span will have a const element type.
*
* std::span will have a constructor that implements this functionality directly.
*/
template<typename A, int N>
constexpr Span<A> MakeSpan(A (&a)[N]) { return Span<A>(a, N); }

template<typename V>
constexpr Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type> MakeSpan(V& v) { return Span<typename std::remove_pointer<decltype(std::declval<V>().data())>::type>(v.data(), v.size()); }

#endif

7 changes: 4 additions & 3 deletions src/test/net_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2012-2016 The Bitcoin Core developers
// Copyright (c) 2018 The BitZeny Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "addrman.h"
Expand Down Expand Up @@ -64,7 +65,7 @@ class CAddrManCorrupted : public CAddrManSerializationMock
CDataStream AddrmanToStream(CAddrManSerializationMock& _addrman)
{
CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
ssPeersIn << FLATDATA(Params().MessageStart());
ssPeersIn << Params().MessageStart();
ssPeersIn << _addrman;
std::string str = ssPeersIn.str();
std::vector<unsigned char> vchData(str.begin(), str.end());
Expand Down Expand Up @@ -110,7 +111,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
BOOST_CHECK(addrman1.size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> FLATDATA(pchMsgTmp);
ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
} catch (const std::exception& e) {
exceptionThrown = true;
Expand Down Expand Up @@ -142,7 +143,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
BOOST_CHECK(addrman1.size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> FLATDATA(pchMsgTmp);
ssPeers1 >> pchMsgTmp;
ssPeers1 >> addrman1;
} catch (const std::exception& e) {
exceptionThrown = true;
Expand Down
Loading

0 comments on commit ce89fde

Please sign in to comment.