Fix memory management and deprecated removal from serialization

Fix missing RsDiscPgpKeyItem initialization
Fix inconsistent new[]/delete[] usage in RsDiscPgpKeyItem and
  PGPHandler::exportPublicKey which now consistently uses malloc/free
Remove deprecated RsGenericSerializer::FORMAT_*
Move from deprecated RsServiceSerializer::SERIALIZATION_FLAG_* to
  RsSerializationFlags
Solve a bunch of compiler warnings
Stricter checks in SerializeContext costructor
This commit is contained in:
Gioacchino Mazzurco 2020-03-18 23:04:16 +01:00
parent 39bde58c29
commit 5610cc8600
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
24 changed files with 230 additions and 244 deletions

View file

@ -4,6 +4,8 @@
* libretroshare: retroshare core library *
* *
* Copyright (C) 2016 Cyril Soler <csoler@users.sourceforge.net> *
* Copyright (C) 2020 Gioacchino Mazzurco <gio@eigenlab.org> *
* Copyright (C) 2020 Asociación Civil Altermundi <info@altermundi.net> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
@ -18,23 +20,17 @@
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
* *
*******************************************************************************/
******************************************************************************/
#include <typeinfo>
#include "rsitems/rsitem.h"
#include "util/rsprint.h"
#include "serialiser/rsserializer.h"
#include "serialiser/rstypeserializer.h"
#include "util/stacktrace.h"
#include "util/rsdebug.h"
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_NONE ( 0x0000 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_CONFIG ( 0x0001 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SIGNATURE ( 0x0002 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_SKIP_HEADER ( 0x0004 );
const SerializationFlags RsGenericSerializer::SERIALIZATION_FLAG_YIELDING ( 0x0008 );
RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
{
if(!data || !size || !*size)
@ -47,11 +43,13 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
return nullptr;
}
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
{
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
return NULL ;
}
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag "
<< "SKIP_HEADER. Check your code!" << std::endl;
print_stacktrace();
return nullptr;
}
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
@ -64,7 +62,9 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(static_cast<uint8_t*>(data)),*size,mFormat,mFlags);
SerializeContext ctx(
const_cast<uint8_t*>(static_cast<uint8_t*>(data)), *size,
mFlags );
ctx.mOffset = 8 ;
item->serial_process(RsGenericSerializer::DESERIALIZE, ctx) ;
@ -85,11 +85,13 @@ RsItem *RsServiceSerializer::deserialise(void *data, uint32_t *size)
}
RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
{
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
{
std::cerr << "(EE) Cannot deserialise item with flags SERIALIZATION_FLAG_SKIP_HEADER. Check your code!" << std::endl;
return NULL ;
}
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
RsErr() << __PRETTY_FUNCTION__ << " Cannot deserialise item with flag "
<< "SKIP_HEADER. Check your code!" << std::endl;
print_stacktrace();
return nullptr;
}
uint32_t rstype = getRsItemId(const_cast<void*>((const void*)data)) ;
@ -102,7 +104,9 @@ RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
return NULL ;
}
SerializeContext ctx(const_cast<uint8_t*>(static_cast<uint8_t*>(data)),*size,mFormat,mFlags);
SerializeContext ctx(
const_cast<uint8_t*>(static_cast<uint8_t*>(data)), *size,
mFlags );
ctx.mOffset = 8 ;
item->serial_process(DESERIALIZE, ctx) ;
@ -121,50 +125,44 @@ RsItem *RsConfigSerializer::deserialise(void *data, uint32_t *size)
delete item ;
return NULL ;
}
bool RsGenericSerializer::serialise(RsItem *item,void *data,uint32_t *size)
bool RsGenericSerializer::serialise(RsItem* item, void* data, uint32_t* size)
{
SerializeContext ctx(static_cast<uint8_t*>(data),0,mFormat,mFlags);
uint32_t tlvsize = this->size(item);
uint32_t tlvsize = this->size(item) ;
constexpr auto fName = __PRETTY_FUNCTION__;
const auto failure = [=](std::error_condition ec)
{
RsErr() << fName << " " << ec << std::endl;
print_stacktrace();
return false;
};
if(tlvsize > *size)
throw std::runtime_error("Cannot serialise: not enough room.") ;
if(tlvsize > *size) return failure(std::errc::no_buffer_space);
SerializeContext ctx(static_cast<uint8_t*>(data), tlvsize, mFlags);
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
ctx.mOffset = 0;
else
if(!(mFlags & RsSerializationFlags::SKIP_HEADER))
{
if(!setRsItemHeader(data, tlvsize, item->PacketId(), tlvsize))
{
std::cerr << "RsSerializer::serialise_item(): ERROR. Not enough size!" << std::endl;
return false ;
}
return failure(std::errc::no_buffer_space);
ctx.mOffset = 8;
}
ctx.mSize = tlvsize;
item->serial_process(RsGenericSerializer::SERIALIZE,ctx);
item->serial_process(RsGenericSerializer::SERIALIZE,ctx) ;
if(ctx.mSize != ctx.mOffset) return failure(std::errc::message_size);
if(ctx.mSize != ctx.mOffset)
{
std::cerr << "RsSerializer::serialise(): ERROR. offset does not match expected size!" << std::endl;
return false ;
}
*size = ctx.mOffset ;
return true ;
*size = ctx.mOffset;
return true;
}
uint32_t RsGenericSerializer::size(RsItem *item)
{
SerializeContext ctx(NULL,0,mFormat,mFlags);
SerializeContext ctx(nullptr, 0, mFlags);
if(mFlags & SERIALIZATION_FLAG_SKIP_HEADER)
ctx.mOffset = 0;
else
ctx.mOffset = 8 ; // header size
if(!!(mFlags & RsSerializationFlags::SKIP_HEADER)) ctx.mOffset = 0;
else ctx.mOffset = 8; // header size
item->serial_process(SIZE_ESTIMATE, ctx) ;
return ctx.mOffset ;
@ -172,7 +170,7 @@ uint32_t RsGenericSerializer::size(RsItem *item)
void RsGenericSerializer::print(RsItem *item)
{
SerializeContext ctx(NULL,0,mFormat,mFlags);
SerializeContext ctx(nullptr, 0, mFlags);
std::cerr << "***** RsItem class: \"" << typeid(*item).name() << "\" *****" << std::endl;
item->serial_process(PRINT, ctx) ;
@ -255,7 +253,7 @@ RsItem *RsRawSerialiser::deserialise(void *data, uint32_t *pktsize)
RsGenericSerializer::SerializeContext::SerializeContext(
uint8_t* data, uint32_t size, SerializationFlags flags,
uint8_t* data, uint32_t size, RsSerializationFlags flags,
RsJson::AllocatorType* allocator ) :
mData(data), mSize(size), mOffset(0), mOk(true), mFlags(flags),
mJson(rapidjson::kObjectType, allocator)
@ -264,20 +262,23 @@ RsGenericSerializer::SerializeContext::SerializeContext(
{
if(size == 0)
{
std::cerr << __PRETTY_FUNCTION__ << " data passed without "
<< "size! This make no sense report to developers!"
<< std::endl;
RsFatal() << __PRETTY_FUNCTION__ << " data passed without "
<< "size! This make no sense report to developers!"
<< std::endl;
print_stacktrace();
exit(-EINVAL);
}
if(flags & SERIALIZATION_FLAG_YIELDING)
if(!!(flags & RsSerializationFlags::YIELDING))
{
std::cerr << __PRETTY_FUNCTION__ << " Attempt to create a "
RsFatal() << __PRETTY_FUNCTION__
<< " Attempt to create a "
<< "binary serialization context with "
<< "SERIALIZATION_FLAG_YIELDING! "
<< "This make no sense report to developers!"
<< std::endl;
print_stacktrace();
exit(-EINVAL);
}
}
}

View file

@ -238,58 +238,23 @@ struct RsGenericSerializer : RsSerialType
FROM_JSON
} SerializeJob;
/** @deprecated use SerializeJob instead */
RS_DEPRECATED typedef enum
{
FORMAT_BINARY = 0x01,
FORMAT_JSON = 0x02
} SerializationFormat;
struct SerializeContext
{
/** Allow shared allocator usage to avoid costly JSON deepcopy for
* nested RsSerializable */
SerializeContext(
uint8_t* data = nullptr, uint32_t size = 0,
SerializationFlags flags = SERIALIZATION_FLAG_NONE,
RsSerializationFlags flags = RsSerializationFlags::NONE,
RsJson::AllocatorType* allocator = nullptr);
RS_DEPRECATED SerializeContext(
uint8_t *data, uint32_t size, SerializationFormat format,
SerializationFlags flags,
RsJson::AllocatorType* allocator = nullptr) :
mData(data), mSize(size), mOffset(0), mOk(true), mFormat(format),
mFlags{flags}, mJson(rapidjson::kObjectType, allocator) {}
unsigned char *mData;
uint32_t mSize;
uint32_t mOffset;
bool mOk;
RS_DEPRECATED SerializationFormat mFormat;
SerializationFlags mFlags;
RsSerializationFlags mFlags;
RsJson mJson;
};
/** These are convenience flags to be used by the items when processing the
* data. The names of the flags are not very important. What matters is that
* the serial_process() method of each item correctly deals with the data
* when it sees the flags, if the serialiser sets them.
* By default the flags are not set and shouldn't be handled.
* When deriving a new serializer, the user can set his own flags, using
* compatible values
*/
static const SerializationFlags SERIALIZATION_FLAG_NONE; // 0x0000
static const SerializationFlags SERIALIZATION_FLAG_CONFIG; // 0x0001
static const SerializationFlags SERIALIZATION_FLAG_SIGNATURE; // 0x0002
static const SerializationFlags SERIALIZATION_FLAG_SKIP_HEADER; // 0x0004
/** Used for JSON deserialization in JSON API, it causes the deserialization
* to continue even if some field is missing (or incorrect), this way the
* API is more user friendly as some methods need just part of the structs
* they take as parameters. */
static const SerializationFlags SERIALIZATION_FLAG_YIELDING; // 0x0008
/**
* The following functions overload RsSerialType.
* They *should not* need to be further overloaded.
@ -302,18 +267,15 @@ struct RsGenericSerializer : RsSerialType
protected:
RsGenericSerializer(
uint8_t serial_class, uint8_t serial_type,
SerializationFormat format, SerializationFlags flags ) :
RsSerializationFlags flags ):
RsSerialType( RS_PKT_VERSION1, serial_class, serial_type),
mFormat(format), mFlags(flags) {}
RsGenericSerializer(
uint16_t service, SerializationFormat format,
SerializationFlags flags ) :
RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFormat(format),
mFlags(flags) {}
SerializationFormat mFormat;
SerializationFlags mFlags;
RsGenericSerializer(
uint16_t service, RsSerializationFlags flags ):
RsSerialType( RS_PKT_VERSION_SERVICE, service ), mFlags(flags) {}
RsSerializationFlags mFlags;
};
@ -323,9 +285,9 @@ protected:
struct RsServiceSerializer : RsGenericSerializer
{
RsServiceSerializer(
uint16_t service_id, SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE ) :
RsGenericSerializer(service_id, format, flags) {}
uint16_t service_id,
RsSerializationFlags flags = RsSerializationFlags::NONE ) :
RsGenericSerializer(service_id, flags) {}
/*! should be overloaded to create the correct type of item depending on the
* data */
@ -342,11 +304,10 @@ struct RsServiceSerializer : RsGenericSerializer
*/
struct RsConfigSerializer : RsGenericSerializer
{
RsConfigSerializer(uint8_t config_class,
uint8_t config_type,
SerializationFormat format = FORMAT_BINARY,
SerializationFlags flags = SERIALIZATION_FLAG_NONE) :
RsGenericSerializer(config_class,config_type,format,flags) {}
RsConfigSerializer(
uint8_t config_class, uint8_t config_type,
RsSerializationFlags flags = RsSerializationFlags::NONE ) :
RsGenericSerializer(config_class, config_type, flags) {}
/*! should be overloaded to create the correct type of item depending on the
* data */

View file

@ -542,7 +542,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
uint32_t serialSize = 0;
RS_SERIAL_PROCESS(serialSize);
if(!ctx.mOk) break;
ctx.mOk = serialSize <= MAX_SERIALIZED_CHUNK_SIZE;
ctx.mOk = serialSize <= MAX_SERIALIZED_CHUNK_SIZE;
if(!ctx.mOk)
{
RsErr() << __PRETTY_FUNCTION__
@ -555,6 +555,8 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
if(!serialSize)
{
Dbg3() << __PRETTY_FUNCTION__ << " Deserialized empty memory chunk"
<< std::endl;
clear();
break;
}
@ -573,7 +575,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
if(serialSize != second)
{
first = reinterpret_cast<uint8_t*>(realloc(first, serialSize));
second = static_cast<uint32_t>(serialSize);
second = serialSize;
}
memcpy(first, ctx.mData + ctx.mOffset, second);
@ -593,8 +595,8 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process(
}
case RsGenericSerializer::FROM_JSON:
{
const bool yelding = !!( RsSerializationFlags::YIELDING &
ctx.mFlags.toEFT<RsSerializationFlags>() );
const bool yelding = !!(
RsSerializationFlags::YIELDING & ctx.mFlags );
if(!(ctx.mOk || yelding))
{
clear();

View file

@ -82,8 +82,7 @@ struct RsTypeSerializer
INTT& member, const std::string& member_name )
{
const bool VLQ_ENCODING = !!(
RsSerializationFlags::INTEGER_VLQ &
ctx.mFlags.toEFT<RsSerializationFlags>() );
RsSerializationFlags::INTEGER_VLQ & ctx.mFlags );
switch(j)
{
@ -149,8 +148,7 @@ struct RsTypeSerializer
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk &= ( ctx.mOk ||
!!( RsSerializationFlags::YIELDING &
ctx.mFlags.toEFT<RsSerializationFlags>() ) )
!!(RsSerializationFlags::YIELDING & ctx.mFlags) )
&& from_JSON(member_name, member, ctx.mJson);
break;
default: fatalUnknownSerialJob(j);
@ -198,7 +196,8 @@ struct RsTypeSerializer
ctx.mOk = ctx.mOk && to_JSON(member_name, member, ctx.mJson);
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk &= (ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
ctx.mOk &= ( ctx.mOk ||
!!(ctx.mFlags & RsSerializationFlags::YIELDING) )
&& from_JSON(member_name, member, ctx.mJson);
break;
default: fatalUnknownSerialJob(j);
@ -236,7 +235,7 @@ struct RsTypeSerializer
break;
case RsGenericSerializer::FROM_JSON:
ctx.mOk &=
(ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING)
(ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING))
&& from_JSON(member_name, type_id, member, ctx.mJson);
break;
default: fatalUnknownSerialJob(j);
@ -324,7 +323,7 @@ struct RsTypeSerializer
{
using namespace rapidjson;
bool ok = ctx.mOk || ctx.mFlags & RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING);
Document& jDoc(ctx.mJson);
Document::AllocatorType& allocator = jDoc.GetAllocator();
@ -424,8 +423,7 @@ struct RsTypeSerializer
RsJson& jDoc(ctx.mJson);
const char* mName = memberName.c_str();
bool hasMember = jDoc.HasMember(mName);
bool yielding = ctx.mFlags &
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING);
if(!hasMember)
{
@ -560,8 +558,7 @@ struct RsTypeSerializer
{
using namespace rapidjson;
bool ok = ctx.mOk || ctx.mFlags &
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
bool ok = ctx.mOk || !!(ctx.mFlags & RsSerializationFlags::YIELDING);
Document& jDoc(ctx.mJson);
Document::AllocatorType& allocator = jDoc.GetAllocator();
@ -669,8 +666,8 @@ struct RsTypeSerializer
break;
case RsGenericSerializer::FROM_JSON:
{
bool ok = ctx.mOk || !!( ctx.mFlags.toEFT<RsSerializationFlags>()
& RsSerializationFlags::YIELDING );
bool ok = ctx.mOk || !!(
ctx.mFlags & RsSerializationFlags::YIELDING );
ctx.mOk = ok && from_JSON(memberName, member, ctx.mJson) && ctx.mOk;
break;
}
@ -760,8 +757,7 @@ struct RsTypeSerializer
RsJson& jDoc(ctx.mJson);
const char* mName = memberName.c_str();
bool hasMember = jDoc.HasMember(mName);
bool yielding = ctx.mFlags &
RsGenericSerializer::SERIALIZATION_FLAG_YIELDING;
bool yielding = !!(ctx.mFlags & RsSerializationFlags::YIELDING);
if(!hasMember)
{