// understanding_strict_aliasing.html
template <typename To, typename From>
static inline To bitwise_cast(From from) {
- BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
+ BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To));
- // BAD!!! These are all broken with -O2.
- //return *reinterpret_cast<To*>(&from); // BAD!!!
- //return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
- //return *(To*)(void*)&from; // BAD!!!
-
- // Super clean and paritally blessed by section 3.9 of the standard.
- //unsigned char c[sizeof(from)];
- //memcpy(c, &from, sizeof(from));
- //To to;
- //memcpy(&to, c, sizeof(c));
- //return to;
-
- // Slightly more questionable.
- // Same code emitted by GCC.
- //To to;
- //memcpy(&to, &from, sizeof(from));
- //return to;
-
- // Technically undefined, but almost universally supported,
- // and the most efficient implementation.
- union {
- From f;
- To t;
- } u;
- u.f = from;
- return u.t;
+ // BAD!!! These are all broken with -O2.
+ //return *reinterpret_cast<To*>(&from); // BAD!!!
+ //return *static_cast<To*>(static_cast<void*>(&from)); // BAD!!!
+ //return *(To*)(void*)&from; // BAD!!!
+
+ // Super clean and paritally blessed by section 3.9 of the standard.
+ //unsigned char c[sizeof(from)];
+ //memcpy(c, &from, sizeof(from));
+ //To to;
+ //memcpy(&to, c, sizeof(c));
+ //return to;
+
+ // Slightly more questionable.
+ // Same code emitted by GCC.
+ //To to;
+ //memcpy(&to, &from, sizeof(from));
+ //return to;
+
+ // Technically undefined, but almost universally supported,
+ // and the most efficient implementation.
+ union {
+ From f;
+ To t;
+ } u;
+ u.f = from;
+ return u.t;
}
uint32_t TBinaryProtocol::writeMessageBegin(const std::string& name,
const TMessageType messageType,
const int32_t seqid) {
- return
- writeString(name) +
- writeByte((int8_t)messageType) +
- writeI32(seqid);
+ if (strict_write_) {
+ int32_t version = (VERSION_1) | ((int32_t)messageType);
+ return
+ writeI32(version) +
+ writeString(name) +
+ writeI32(seqid);
+ } else {
+ return
+ writeString(name) +
+ writeByte((int8_t)messageType) +
+ writeI32(seqid);
+ }
}
uint32_t TBinaryProtocol::writeMessageEnd() {
uint32_t TBinaryProtocol::readMessageBegin(std::string& name,
TMessageType& messageType,
int32_t& seqid) {
-
uint32_t result = 0;
- int8_t type;
- result+= readString(name);
- result+= readByte(type);
- messageType = (TMessageType)type;
- result+= readI32(seqid);
+ int32_t sz;
+ result += readI32(sz);
+
+ if (sz < 0) {
+ // Check for correct version number
+ int32_t version = sz & VERSION_MASK;
+ if (version != VERSION_1) {
+ throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier");
+ }
+ messageType = (TMessageType)(sz & 0x000000ff);
+ result += readString(name);
+ result += readI32(seqid);
+ } else {
+ if (strict_read_) {
+ throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?");
+ } else {
+ // Handle pre-versioned input
+ int8_t type;
+ result += readStringBody(name, sz);
+ result += readByte(type);
+ messageType = (TMessageType)type;
+ result += readI32(seqid);
+ }
+ }
return result;
}
uint32_t result;
int32_t size;
result = readI32(size);
+ return result + readStringBody(str, size);
+}
+
+uint32_t TBinaryProtocol::readStringBody(string& str, int32_t size) {
+ uint32_t result = 0;
// Catch error cases
if (size < 0) {
}
trans_->readAll(string_buf_, size);
str = string((char*)string_buf_, size);
-
- return result + (uint32_t)size;
+ return (uint32_t)size;
}
}}} // facebook::thrift::protocol
* @author Mark Slee <mcslee@facebook.com>
*/
class TBinaryProtocol : public TProtocol {
+ protected:
+ static const int32_t VERSION_MASK = 0xffff0000;
+ static const int32_t VERSION_1 = 0x80010000;
+
public:
TBinaryProtocol(boost::shared_ptr<TTransport> trans) :
TProtocol(trans),
string_limit_(0),
container_limit_(0),
+ strict_read_(false),
+ strict_write_(true),
string_buf_(NULL),
string_buf_size_(0) {}
TBinaryProtocol(boost::shared_ptr<TTransport> trans,
int32_t string_limit,
- int32_t container_limit) :
+ int32_t container_limit,
+ bool strict_read,
+ bool strict_write) :
TProtocol(trans),
string_limit_(string_limit),
container_limit_(container_limit),
+ strict_read_(strict_read),
+ strict_write_(strict_write),
string_buf_(NULL),
string_buf_size_(0) {}
container_limit_ = container_limit;
}
+ void setStrict(bool strict_read, bool strict_write) {
+ strict_read_ = strict_read;
+ strict_write_ = strict_write;
+ }
+
/**
* Writing functions.
*/
uint32_t readString(std::string& str);
+ protected:
+ uint32_t readStringBody(std::string& str, int32_t sz);
+
private:
int32_t string_limit_;
int32_t container_limit_;
+ // Enforce presence of version identifier
+ bool strict_read_;
+ bool strict_write_;
+
// Buffer for reading strings, save for the lifetime of the protocol to
// avoid memory churn allocating memory on every string read
uint8_t* string_buf_;
public:
TBinaryProtocolFactory() :
string_limit_(0),
- container_limit_(0) {}
+ container_limit_(0),
+ strict_read_(false),
+ strict_write_(true) {}
- TBinaryProtocolFactory(int32_t string_limit, int32_t container_limit) :
+ TBinaryProtocolFactory(int32_t string_limit, int32_t container_limit, bool strict_read, bool strict_write) :
string_limit_(string_limit),
- container_limit_(container_limit) {}
+ container_limit_(container_limit),
+ strict_read_(strict_read),
+ strict_write_(strict_write) {}
virtual ~TBinaryProtocolFactory() {}
container_limit_ = container_limit;
}
+ void setStrict(bool strict_read, bool strict_write) {
+ strict_read_ = strict_read;
+ strict_write_ = strict_write;
+ }
+
boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
- return boost::shared_ptr<TProtocol>(new TBinaryProtocol(trans, string_limit_, container_limit_));
+ return boost::shared_ptr<TProtocol>(new TBinaryProtocol(trans, string_limit_, container_limit_, strict_read_, strict_write_));
}
private:
int32_t string_limit_;
int32_t container_limit_;
+ bool strict_read_;
+ bool strict_write_;
};
UNKNOWN = 0,
INVALID_DATA = 1,
NEGATIVE_SIZE = 2,
- SIZE_LIMIT = 3
+ SIZE_LIMIT = 3,
+ BAD_VERSION = 4,
};
TProtocolException() :
*/
public class TBinaryProtocol extends TProtocol {
+ protected static final int VERSION_MASK = 0xffff0000;
+ protected static final int VERSION_1 = 0x80010000;
+
+ protected boolean strictRead_ = false;
+ protected boolean strictWrite_ = true;
+
/**
* Factory
*/
public static class Factory implements TProtocolFactory {
+ protected boolean strictRead_ = false;
+ protected boolean strictWrite_ = true;
+
+ public Factory() {
+ this(false, false);
+ }
+
+ public Factory(boolean strictRead, boolean strictWrite) {
+ strictRead_ = strictRead;
+ strictWrite_ = strictWrite;
+ }
+
public TProtocol getProtocol(TTransport trans) {
- return new TBinaryProtocol(trans);
+ return new TBinaryProtocol(trans, strictRead_, strictWrite_);
}
}
* Constructor
*/
public TBinaryProtocol(TTransport trans) {
+ this(trans, false, false);
+ }
+
+ public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) {
super(trans);
+ strictRead_ = strictRead;
+ strictWrite_ = strictWrite;
}
+
public void writeMessageBegin(TMessage message) throws TException {
- writeString(message.name);
- writeByte(message.type);
- writeI32(message.seqid);
+ if (strictWrite_) {
+ int version = VERSION_1 | message.type;
+ writeI32(version);
+ writeString(message.name);
+ writeI32(message.seqid);
+ } else {
+ writeString(message.name);
+ writeByte(message.type);
+ writeI32(message.seqid);
+ }
}
public void writeMessageEnd() {}
public TMessage readMessageBegin() throws TException {
TMessage message = new TMessage();
- message.name = readString();
- message.type = readByte();
- message.seqid = readI32();
+
+ int size = readI32();
+ if (size < 0) {
+ int version = size & VERSION_MASK;
+ if (version != VERSION_1) {
+ throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin");
+ }
+ message.type = (byte)(version & 0x000000ff);
+ message.name = readString();
+ message.seqid = readI32();
+ } else {
+ if (strictRead_) {
+ throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?");
+ }
+ message.name = readStringBody(size);
+ message.type = readByte();
+ message.seqid = readI32();
+ }
return message;
}
public String readString() throws TException {
int size = readI32();
+ return readStringBody(size);
+ }
+
+ public String readStringBody(int size) throws TException {
byte[] buf = new byte[size];
trans_.readAll(buf, 0, size);
return new String(buf);
public static final int INVALID_DATA = 1;
public static final int NEGATIVE_SIZE = 2;
public static final int SIZE_LIMIT = 3;
+ public static final int BAD_VERSION = 4;
protected int type_ = UNKNOWN;
new Options());
}
+ public TThreadPoolServer(TProcessor processor,
+ TServerTransport serverTransport,
+ TProtocolFactory protocolFactory) {
+ this(processor, serverTransport,
+ new TTransportFactory(), new TTransportFactory(),
+ protocolFactory, protocolFactory,
+ new Options());
+ }
+
public TThreadPoolServer(TProcessor processor,
TServerTransport serverTransport,
TTransportFactory transportFactory,
package Thrift::BinaryProtocol;
use base('Thrift::Protocol');
+use constant VERSION_MASK => 0xffff0000;
+use constant VERSION_1 => 0x80010000;
+
sub new
{
my $classname = shift;
my ($name, $type, $seqid) = @_;
return
+ $self->writeI32(VERSION_1 | $type) +
$self->writeString($name) +
- $self->writeByte($type) +
$self->writeI32($seqid);
}
my $self = shift;
my ($name, $type, $seqid) = @_;
+ my $version = 0;
+ my $result = $self->readI32($version);
+ if ($version & VERSION_MASK != VERSION_1) {
+ die new Thrift::TException('Missing version identifier')
+ }
+ $$type = $version & 0x000000ff;
return
+ $result +
$self->readString($name) +
- $self->readByte($type) +
$self->readI32($seqid);
}
use constant INVALID_DATA => 1;
use constant NEGATIVE_SIZE => 2;
use constant SIZE_LIMIT => 3;
-
+use constant BAD_VERSION => 4;
sub new {
my $classname = shift;
*/
class TBinaryProtocol extends TProtocol {
- public function __construct($trans) {
+ const VERSION_MASK = 0xffff0000;
+ const VERSION_1 = 0x80010000;
+
+ private $strictRead_ = false;
+ private $strictWrite_ = true;
+
+ public function __construct($trans, $strictRead=false, $strictWrite=true) {
parent::__construct($trans);
+ $this->strictRead_ = $strictRead;
+ $this->strictWrite_ = $strictWrite;
}
public function writeMessageBegin($name, $type, $seqid) {
- return
- $this->writeString($name) +
- $this->writeByte($type) +
- $this->writeI32($seqid);
+ if ($this->strictWrite_) {
+ $version = self::VERSION_1 | $type;
+ return
+ $this->writeI32($version) +
+ $this->writeString($name) +
+ $this->writeI32($seqid);
+ } else {
+ return
+ $this->writeString($name) +
+ $this->writeByte($type) +
+ $this->writeI32($seqid);
+ }
}
public function writeMessageEnd() {
public function writeFieldEnd() {
return 0;
- }
+ }
public function writeFieldStop() {
return
public function writeI64($value) {
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
- // as signed and any int over 2^31 - 1 as a float
+ // as signed and any int over 2^31 - 1 as a float
if (PHP_INT_SIZE == 4) {
$neg = $value < 0;
if ($neg) {
- $value *= -1;
+ $value *= -1;
}
-
+
$hi = (int)($value / 4294967296);
$lo = (int)$value;
-
+
if ($neg) {
- $hi = ~$hi;
- $lo = ~$lo;
- if (($lo & (int)0xffffffff) == (int)0xffffffff) {
- $lo = 0;
- $hi++;
- } else {
- $lo++;
- }
+ $hi = ~$hi;
+ $lo = ~$lo;
+ if (($lo & (int)0xffffffff) == (int)0xffffffff) {
+ $lo = 0;
+ $hi++;
+ } else {
+ $lo++;
+ }
}
$data = pack('N2', $hi, $lo);
-
+
} else {
$hi = $value >> 32;
$lo = $value & 0xFFFFFFFF;
}
public function readMessageBegin(&$name, &$type, &$seqid) {
- return
- $this->readString($name) +
- $this->readByte($type) +
- $this->readI32($seqid);
+ $result = $this->readI32($sz);
+ if ($sz < 0) {
+ $version = $sz & self::VERSION_MASK;
+ if ($version != self::VERSION_1) {
+ throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
+ }
+ $type = $sz & 0x000000ff;
+ $result +=
+ $this->readString($name) +
+ $this->readI32($seqid);
+ } else {
+ if ($this->strictRead_) {
+ throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
+ } else {
+ // Handle pre-versioned input
+ $name = $this->trans_->readAll($sz);
+ $result +=
+ $sz +
+ $this->readByte($type) +
+ $this->readI32($seqid);
+ }
+ }
+ return $result;
}
public function readMessageEnd() {
$data = $this->trans_->readAll(8);
$arr = unpack('N2', $data);
-
+
// If we are on a 32bit architecture we have to explicitly deal with
// 64-bit twos-complement arithmetic since PHP wants to treat all ints
// as signed and any int over 2^31 - 1 as a float
* Binary Protocol Factory
*/
class TBinaryProtocolFactory implements TProtocolFactory {
+ private $strictRead_ = false;
+ private $strictWrite_ = false;
+
+ public function __construct($strictRead=false, $strictWrite=false) {
+ $this->strictRead_ = $strictRead;
+ $this->strictWrite_ = $strictWrite;
+ }
+
public function getProtocol($trans) {
- return new TBinaryProtocol($trans);
+ return new TBinaryProtocol($trans, $this->strictRead, $this->strictWrite);
}
}
const INVALID_DATA = 1;
const NEGATIVE_SIZE = 2;
const SIZE_LIMIT = 3;
+ const BAD_VERSION = 4;
function __construct($message=null, $code=0) {
parent::__construct($message, $code);
"""Binary implementation of the Thrift protocol driver."""
- def __init__(self, trans):
+ VERSION_MASK = 0xffff0000
+ VERSION_1 = 0x80010000
+
+ def __init__(self, trans, strictRead=False, strictWrite=True):
TProtocolBase.__init__(self, trans)
+ self.strictRead = strictRead
+ self.strictWrite = strictWrite
def writeMessageBegin(self, name, type, seqid):
- self.writeString(name)
- self.writeByte(type)
- self.writeI32(seqid)
+ if self.strictWrite:
+ self.writeI32(VERSION_1 | type)
+ self.writeString(name)
+ self.writeI32(seqid)
+ else:
+ self.writeString(name)
+ self.writeByte(type)
+ self.writeI32(seqid)
def writeMessageEnd(self):
pass
self.trans.write(str)
def readMessageBegin(self):
- name = self.readString()
- type = self.readByte()
- seqid = self.readI32()
+ sz = self.readI32()
+ if sz < 0:
+ version = sz & VERSION_MASK
+ if version != VERSION_1:
+ raise TProtocolException(TProtocolException.BAD_VERSION, 'Bad version in readMessageBegin: %d' % (sz))
+ type = version & 0x000000ff
+ name = self.readString()
+ seqid = self.readI32()
+ else:
+ if self.strictRead:
+ raise TProtocolException(TProtocolException.BAD_VERSION, 'No protocol version header')
+ name = self.trans.readAll(sz)
+ type = self.readByte()
+ seqid = self.readI32()
return (name, type, seqid)
def readMessageEnd(self):
return str
class TBinaryProtocolFactory:
+ def __init__(self, strictRead=False, strictWrite=True):
+ self.strictRead = strictRead
+ self.strictWrite = strictWrite
+
def getProtocol(self, trans):
- prot = TBinaryProtocol(trans)
+ prot = TBinaryProtocol(trans, self.strictRead, self.strictWrite)
return prot
INVALID_DATA = 1
NEGATIVE_SIZE = 2
SIZE_LIMIT = 3
+ BAD_VERSION = 4
def __init__(self, type=UNKNOWN, message=None):
TException.__init__(self, message)
require 'thrift/protocol/tprotocol'
class TBinaryProtocol < TProtocol
+
+ VERSION_MASK = 0xffff0000
+ VERSION_1 = 0x80010000
+
def initialize(trans)
super(trans)
end
def writeMessageBegin(name, type, seqid)
+ writeI32(VERSION_1 & type)
writeString(name)
- writeByte(type)
writeI32(seqid)
end
end
def readMessageBegin()
+ version = readI32()
+ if (version & VERSION_MASK != VERSION_1)
+ raise TProtocolException.new(TProtocolException::BAD_VERSION, 'Missing version identifier')
+ end
+ type = version & 0x000000ff
name = readString()
- type = readByte()
seqid = readI32()
return name, type, seqid
end
require 'thrift/thrift'
+class TProtocolException < TException
+
+ UNKNOWN = 0
+ INVALID_DATA = 1
+ NEGATIVE_SIZE = 2
+ SIZE_LIMIT = 3
+ BAD_VERSION = 4
+
+ attr_reader :type
+
+ def initialize(type=UNKNOWN, message=nil)
+ super(message)
+ @type = type
+ end
+
+end
+
class TProtocol
attr_reader :trans