Skip to content

Commit 5459116

Browse files
committed
Merge pull request #4293
fa126ef Avoid undefined behavior using CFlatData in CScript serialization (Wladimir J. van der Laan)
2 parents 52d4abf + fa126ef commit 5459116

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/script.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,12 @@ class CScriptCompressor
770770
void Serialize(Stream &s, int nType, int nVersion) const {
771771
std::vector<unsigned char> compr;
772772
if (Compress(compr)) {
773-
s << CFlatData(&compr[0], &compr[compr.size()]);
773+
s << CFlatData(compr);
774774
return;
775775
}
776776
unsigned int nSize = script.size() + nSpecialScripts;
777777
s << VARINT(nSize);
778-
s << CFlatData(&script[0], &script[script.size()]);
778+
s << CFlatData(script);
779779
}
780780

781781
template<typename Stream>
@@ -784,13 +784,13 @@ class CScriptCompressor
784784
s >> VARINT(nSize);
785785
if (nSize < nSpecialScripts) {
786786
std::vector<unsigned char> vch(GetSpecialSize(nSize), 0x00);
787-
s >> REF(CFlatData(&vch[0], &vch[vch.size()]));
787+
s >> REF(CFlatData(vch));
788788
Decompress(nSize, vch);
789789
return;
790790
}
791791
nSize -= nSpecialScripts;
792792
script.resize(nSize);
793-
s >> REF(CFlatData(&script[0], &script[script.size()]));
793+
s >> REF(CFlatData(script));
794794
}
795795
};
796796

src/serialize.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,34 @@ inline T& REF(const T& val)
3737
return const_cast<T&>(val);
3838
}
3939

40+
/** Get begin pointer of vector (non-const version).
41+
* @note These functions avoid the undefined case of indexing into an empty
42+
* vector, as well as that of indexing after the end of the vector.
43+
*/
44+
template <class T, class TAl>
45+
inline T* begin_ptr(std::vector<T,TAl>& v)
46+
{
47+
return v.empty() ? NULL : &v[0];
48+
}
49+
/** Get begin pointer of vector (const version) */
50+
template <class T, class TAl>
51+
inline const T* begin_ptr(const std::vector<T,TAl>& v)
52+
{
53+
return v.empty() ? NULL : &v[0];
54+
}
55+
/** Get end pointer of vector (non-const version) */
56+
template <class T, class TAl>
57+
inline T* end_ptr(std::vector<T,TAl>& v)
58+
{
59+
return v.empty() ? NULL : (&v[0] + v.size());
60+
}
61+
/** Get end pointer of vector (const version) */
62+
template <class T, class TAl>
63+
inline const T* end_ptr(const std::vector<T,TAl>& v)
64+
{
65+
return v.empty() ? NULL : (&v[0] + v.size());
66+
}
67+
4068
/////////////////////////////////////////////////////////////////
4169
//
4270
// Templates for serializing to anything that looks like a stream,
@@ -318,6 +346,12 @@ class CFlatData
318346
char* pend;
319347
public:
320348
CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { }
349+
template <class T, class TAl>
350+
explicit CFlatData(std::vector<T,TAl> &v)
351+
{
352+
pbegin = (char*)begin_ptr(v);
353+
pend = (char*)end_ptr(v);
354+
}
321355
char* begin() { return pbegin; }
322356
const char* begin() const { return pbegin; }
323357
char* end() { return pend; }

0 commit comments

Comments
 (0)