Use vector_uchar instead of string for binary network/file data

This distinction allows us to better support Python 3, since it will raise exceptions when trying to put arbitrary binary data in a str object.

This also adds some convenience functions for efficiently initializing a Datagram or PTA_uchar from a vector_uchar.
This commit is contained in:
rdb 2018-04-02 23:16:03 +02:00
parent fadbcd91e5
commit e9ae7dcc40
25 changed files with 143 additions and 167 deletions

View File

@ -803,8 +803,9 @@ handle_update_field_owner() {
Py_DECREF(dclass_this);
// check if we should forward this update to the owner view
vector_uchar data = _di.get_remaining_bytes();
DCPacker packer;
packer.set_unpack_data(_di.get_remaining_bytes());
packer.set_unpack_data((const char *)data.data(), data.size(), false);
int field_id = packer.raw_unpack_uint16();
DCField *field = dclass->get_field_by_index(field_id);
if (field->is_ownrecv()) {
@ -845,8 +846,9 @@ handle_update_field_owner() {
Py_DECREF(dclass_this);
// check if we should forward this update to the owner view
vector_uchar data = _di.get_remaining_bytes();
DCPacker packer;
packer.set_unpack_data(_di.get_remaining_bytes());
packer.set_unpack_data((const char *)data.data(), data.size(), false);
int field_id = packer.raw_unpack_uint16();
DCField *field = dclass->get_field_by_index(field_id);
if (true) {//field->is_broadcast()) {

View File

@ -146,14 +146,15 @@ open_read(istream *source, bool owns_source, const string &password) {
int iv_length = EVP_CIPHER_iv_length(cipher);
_read_block_size = EVP_CIPHER_block_size(cipher);
string iv = sr.extract_bytes(iv_length);
unsigned char *iv = (unsigned char *)alloca(iv_length);
iv_length = (int)sr.extract_bytes(iv, iv_length);
_read_ctx = EVP_CIPHER_CTX_new();
nassertv(_read_ctx != NULL);
// Initialize the context
int result;
result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv.data());
result = EVP_DecryptInit(_read_ctx, cipher, NULL, (unsigned char *)iv);
nassertv(result > 0);
result = EVP_CIPHER_CTX_set_key_length(_read_ctx, key_length);
@ -170,7 +171,7 @@ open_read(istream *source, bool owns_source, const string &password) {
unsigned char *key = (unsigned char *)alloca(key_length);
result =
PKCS5_PBKDF2_HMAC_SHA1((const char *)password.data(), password.length(),
(unsigned char *)iv.data(), iv.length(),
iv, iv_length,
count * iteration_count_factor + 1,
key_length, key);
nassertv(result > 0);

View File

@ -117,16 +117,18 @@ extract_bytes(unsigned char *into, size_t size) {
* Extracts the indicated number of bytes in the stream and returns them as a
* string. Returns empty string at end-of-file.
*/
string StreamReader::
vector_uchar StreamReader::
extract_bytes(size_t size) {
vector_uchar buffer;
if (_in->eof() || _in->fail()) {
return string();
return buffer;
}
char *buffer = (char *)alloca(size);
_in->read(buffer, size);
buffer.resize(size);
_in->read((char *)&buffer[0], size);
size_t read_bytes = _in->gcount();
return string(buffer, read_bytes);
buffer.resize(read_bytes);
return buffer;
}
/**

View File

@ -19,6 +19,7 @@
#include "numeric_types.h"
#include "littleEndian.h"
#include "bigEndian.h"
#include "vector_uchar.h"
/**
* A class to read sequential binary data directly from an istream. Its
@ -71,7 +72,7 @@ PUBLISHED:
EXTENSION(BLOCKING PyObject *readlines());
public:
BLOCKING string extract_bytes(size_t size);
BLOCKING vector_uchar extract_bytes(size_t size);
BLOCKING string readline();
private:

View File

@ -583,9 +583,7 @@ add_multifile_record(PT(MultifileRecord) mfr) {
* Verifies magic number, returns the number of multifiles or -1 if invalid
*/
int DownloadDb::Db::
parse_header(const string &data) {
Datagram dg(data);
parse_header(Datagram dg) {
// Make sure we have a good header
DatagramIterator di(dg);
uint32_t magic_number = di.get_uint32();
@ -623,8 +621,7 @@ parse_header(const string &data) {
* record
*/
int DownloadDb::Db::
parse_record_header(const string &data) {
Datagram dg(data);
parse_record_header(Datagram dg) {
DatagramIterator di(dg);
int32_t record_length = di.get_int32();
downloader_cat.spam()
@ -639,14 +636,12 @@ parse_record_header(const string &data) {
* Parses a multifile record (mfr) and returns one
*/
PT(DownloadDb::MultifileRecord) DownloadDb::Db::
parse_mfr(const string &data) {
parse_mfr(Datagram dg) {
PT(DownloadDb::MultifileRecord) mfr = new DownloadDb::MultifileRecord;
Datagram dg(data);
DatagramIterator di(dg);
int32_t mfr_name_length = di.get_int32();
mfr->_name = di.extract_bytes(mfr_name_length);
mfr->_name = di.get_string32();
mfr->_phase = di.get_float64();
mfr->_size = di.get_int32();
mfr->_status = di.get_int32();
@ -676,14 +671,12 @@ parse_mfr(const string &data) {
* Parses a file record (fr) and returns one
*/
PT(DownloadDb::FileRecord) DownloadDb::Db::
parse_fr(const string &data) {
parse_fr(Datagram dg) {
PT(DownloadDb::FileRecord) fr = new DownloadDb::FileRecord;
Datagram dg(data);
DatagramIterator di(dg);
int32_t fr_name_length = di.get_int32();
fr->_name = di.extract_bytes(fr_name_length);
fr->_name = di.get_string32();
// At one time, we stored files in the database with a backslash separator.
// Nowadays we use a forward slash, but we should make sure we properly
@ -706,15 +699,14 @@ parse_fr(const string &data) {
bool DownloadDb::Db::
read(StreamReader &sr, bool want_server_info) {
// Read the header
string header;
header = sr.extract_bytes(_header_length);
vector_uchar header = sr.extract_bytes(_header_length);
if (header.size() != (size_t)_header_length) {
downloader_cat.error() << "truncated db file" << endl;
return false;
}
// Parse the header
int num_multifiles = parse_header(header);
int num_multifiles = parse_header(Datagram(move(header)));
if (num_multifiles < 0) {
downloader_cat.error() << "invalid db header" << endl;
return false;
@ -727,26 +719,26 @@ read(StreamReader &sr, bool want_server_info) {
// of the record
int mfr_header_length = sizeof(int32_t);
string mfr_header = sr.extract_bytes(mfr_header_length);
vector_uchar mfr_header = sr.extract_bytes(mfr_header_length);
if (mfr_header.size() != (size_t)mfr_header_length) {
downloader_cat.error() << "invalid mfr header" << endl;
return false;
}
// Parse the header
int mfr_length = parse_record_header(mfr_header);
int mfr_length = parse_record_header(Datagram(move(mfr_header)));
// Ok, now that we know the size of the mfr, read it in Make a buffer to
// read the multifile record into do not count the header length twice
int read_length = (mfr_length - mfr_header_length);
string mfr_record = sr.extract_bytes(read_length);
vector_uchar mfr_record = sr.extract_bytes(read_length);
if (mfr_record.size() != (size_t)read_length) {
downloader_cat.error() << "invalid mfr record" << endl;
return false;
}
// Parse the mfr
PT(DownloadDb::MultifileRecord) mfr = parse_mfr(mfr_record);
PT(DownloadDb::MultifileRecord) mfr = parse_mfr(Datagram(move(mfr_record)));
// Only read in the individual file info if you are the server
if (want_server_info) {
@ -758,27 +750,27 @@ read(StreamReader &sr, bool want_server_info) {
int fr_header_length = sizeof(int32_t);
// Read the header
string fr_header = sr.extract_bytes(fr_header_length);
vector_uchar fr_header = sr.extract_bytes(fr_header_length);
if (fr_header.size() != (size_t)fr_header_length) {
downloader_cat.error() << "invalid fr header" << endl;
return false;
}
// Parse the header
int fr_length = parse_record_header(fr_header);
int fr_length = parse_record_header(Datagram(move(fr_header)));
// Ok, now that we know the size of the mfr, read it in do not count
// the header length twice
int read_length = (fr_length - fr_header_length);
string fr_record = sr.extract_bytes(read_length);
vector_uchar fr_record = sr.extract_bytes(read_length);
if (fr_record.size() != (size_t)read_length) {
downloader_cat.error() << "invalid fr record" << endl;
return false;
}
// Parse the file record
PT(DownloadDb::FileRecord) fr = parse_fr(fr_record);
PT(DownloadDb::FileRecord) fr = parse_fr(Datagram(move(fr_record)));
// Add this file record to the current multifilerecord
mfr->add_file_record(fr);
@ -900,12 +892,10 @@ write_header(ostream &write_stream) {
// Write the number of multifiles
dg.add_int32(get_num_multifiles());
string msg = dg.get_message();
// Seek back to the beginning of the write stream
write_stream.seekp(0);
// Overwrite the old bogus header with the real header
write_stream.write(msg.data(), msg.length());
write_stream.write((const char *)dg.get_data(), dg.get_length());
return true;
}
@ -1100,17 +1090,8 @@ read_version_map(StreamReader &sr) {
for (int i = 0; i < num_entries; i++) {
// Get the length of the file name
int name_length = sr.get_int32();
if (sr.get_istream()->fail()) {
return false;
}
downloader_cat.spam()
<< "DownloadDb::read_version_map() - name length: " << name_length
<< endl;
// Get the file name
string name = sr.extract_bytes(name_length);
string name = sr.get_string32();
downloader_cat.spam()
<< "DownloadDb::read_version_map() - name: " << name << endl;

View File

@ -171,10 +171,10 @@ public:
bool multifile_exists(string mfname) const;
PT(MultifileRecord) get_multifile_record_named(string mfname) const;
void add_multifile_record(PT(MultifileRecord) mfr);
int parse_header(const string &data);
int parse_record_header(const string &data);
PT(MultifileRecord) parse_mfr(const string &data);
PT(FileRecord) parse_fr(const string &data);
int parse_header(Datagram dg);
int parse_record_header(Datagram dg);
PT(MultifileRecord) parse_mfr(Datagram dg);
PT(FileRecord) parse_fr(Datagram dg);
bool read(StreamReader &sr, bool want_server_info);
bool write(StreamWriter &sw, bool want_server_info);
Filename _filename;

View File

@ -50,17 +50,17 @@ SSReader::
bool SSReader::
do_receive_datagram(Datagram &dg) {
if (_tcp_header_size == 0) {
_data_expected = _data_so_far.length();
_data_expected = _data_so_far.size();
}
if (_data_expected == 0) {
// Read the first two bytes: the datagram length.
while ((int)_data_so_far.length() < _tcp_header_size) {
while ((int)_data_so_far.size() < _tcp_header_size) {
int ch = _istream->get();
if (_istream->eof() || _istream->fail()) {
_istream->clear();
return false;
}
_data_so_far += (char)ch;
_data_so_far.push_back((unsigned char)ch);
}
Datagram header(_data_so_far);
@ -70,7 +70,7 @@ do_receive_datagram(Datagram &dg) {
} else if (_tcp_header_size == 4) {
_data_expected = di.get_uint32();
}
_data_so_far = _data_so_far.substr(_tcp_header_size);
_data_so_far.erase(_data_so_far.begin(), _data_so_far.begin() + _tcp_header_size);
if (_data_expected == 0) {
// Empty datagram.
@ -84,20 +84,19 @@ do_receive_datagram(Datagram &dg) {
static const size_t buffer_size = 1024;
char buffer[buffer_size];
size_t read_count = min(_data_expected - _data_so_far.length(),
buffer_size);
size_t read_count = min(_data_expected - _data_so_far.size(), buffer_size);
_istream->read(buffer, read_count);
size_t count = _istream->gcount();
while (count != 0) {
_data_so_far.append(buffer, count);
_data_so_far.insert(_data_so_far.end(), buffer, buffer + count);
read_count = min(_data_expected - _data_so_far.length(),
read_count = min(_data_expected - _data_so_far.size(),
buffer_size);
_istream->read(buffer, read_count);
count = _istream->gcount();
}
if (_data_so_far.length() < _data_expected) {
if (_data_so_far.size() < _data_expected) {
// Not yet here. Clear the istream error flag and return false to
// indicate more coming.
_istream->clear();
@ -108,7 +107,7 @@ do_receive_datagram(Datagram &dg) {
dg.append_data(_data_so_far);
_data_expected = 0;
_data_so_far = string();
_data_so_far.clear();
return true;
}

View File

@ -21,6 +21,7 @@
#include "pdeque.h"
#include "typedReferenceCount.h"
#include "pointerTo.h"
#include "vector_uchar.h"
// At the present, this module is not compiled if OpenSSL is not available,
// since the only current use for it is to implement OpenSSL-defined
@ -54,7 +55,7 @@ private:
istream *_istream;
size_t _data_expected;
string _data_so_far;
vector_uchar _data_so_far;
int _tcp_header_size;
#ifdef SIMULATE_NETWORK_DELAY

View File

@ -42,58 +42,16 @@ Datagram(const void *data, size_t size) :
* Constructs a datagram from an existing block of data.
*/
INLINE Datagram::
Datagram(const string &data) :
Datagram(vector_uchar data) :
_data(move(data)),
#ifdef STDFLOAT_DOUBLE
_stdfloat_double(true)
#else
_stdfloat_double(false)
#endif
{
append_data(data);
}
/**
*
*/
INLINE Datagram::
Datagram(const Datagram &copy) :
_data(copy._data),
_stdfloat_double(copy._stdfloat_double)
{
}
/**
*
*/
INLINE void Datagram::
operator = (const Datagram &copy) {
_data = copy._data;
_stdfloat_double = copy._stdfloat_double;
}
#ifdef USE_MOVE_SEMANTICS
/**
*
*/
INLINE Datagram::
Datagram(Datagram &&from) NOEXCEPT :
_data(move(from._data)),
_stdfloat_double(from._stdfloat_double)
{
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
*
*/
INLINE void Datagram::
operator = (Datagram &&from) NOEXCEPT {
_data = move(from._data);
_stdfloat_double = from._stdfloat_double;
}
#endif // USE_MOVE_SEMANTICS
/**
* Adds a boolean value to the datagram.
*/
@ -291,7 +249,7 @@ add_string(const string &str) {
add_uint16((uint16_t)str.length());
// Add the string
append_data(str);
append_data(str.data(), str.length());
}
/**
@ -304,18 +262,18 @@ add_string32(const string &str) {
add_uint32((uint32_t)str.length());
// Add the string
append_data(str);
append_data(str.data(), str.length());
}
/**
* Adds a variable-length string to the datagram, as a NULL-terminated string.
*/
INLINE void Datagram::
add_z_string(string str) {
add_z_string(const string &str) {
// We must not have any nested null characters in the string.
size_t null_pos = str.find('\0');
// Add the string (sans the null character).
append_data(str.substr(0, null_pos));
append_data(str.data(), std::min<size_t>(null_pos, str.length()));
// And the null character.
add_uint8('\0');
@ -329,11 +287,11 @@ add_z_string(string str) {
INLINE void Datagram::
add_fixed_string(const string &str, size_t size) {
if (str.length() < size) {
append_data(str);
append_data(str.data(), str.length());
pad_bytes(size - str.length());
} else { // str.length() >= size
append_data(str.substr(0, size));
append_data(str.data(), size);
}
}
@ -341,8 +299,8 @@ add_fixed_string(const string &str, size_t size) {
* Appends some more raw data to the end of the datagram.
*/
INLINE void Datagram::
append_data(const string &data) {
append_data(data.data(), data.length());
append_data(const vector_uchar &data) {
append_data(data.data(), data.size());
}
/**

View File

@ -39,14 +39,7 @@ class EXPCL_PANDAEXPRESS Datagram : public TypedObject {
PUBLISHED:
INLINE Datagram();
INLINE Datagram(const void *data, size_t size);
INLINE Datagram(const string &data);
INLINE Datagram(const Datagram &copy);
INLINE void operator = (const Datagram &copy);
#ifdef USE_MOVE_SEMANTICS
INLINE Datagram(Datagram &&from) NOEXCEPT;
INLINE void operator = (Datagram &&from) NOEXCEPT;
#endif
INLINE explicit Datagram(vector_uchar data);
virtual ~Datagram();
@ -80,13 +73,13 @@ PUBLISHED:
INLINE void add_string(const string &str);
INLINE void add_string32(const string &str);
INLINE void add_z_string(string str);
INLINE void add_z_string(const string &str);
INLINE void add_fixed_string(const string &str, size_t size);
void add_wstring(const wstring &str);
void pad_bytes(size_t size);
void append_data(const void *data, size_t size);
INLINE void append_data(const string &data);
INLINE void append_data(const vector_uchar &data);
void assign(const void *data, size_t size);

View File

@ -422,14 +422,13 @@ skip_bytes(size_t size) {
* Returns the remaining bytes in the datagram as a string, but does not
* extract them from the iterator.
*/
INLINE string DatagramIterator::
INLINE vector_uchar DatagramIterator::
get_remaining_bytes() const {
nassertr(_datagram != (const Datagram *)NULL, "");
nassertr(_current_index <= _datagram->get_length(), "");
nassertr(_datagram != (const Datagram *)NULL, vector_uchar());
nassertr(_current_index <= _datagram->get_length(), vector_uchar());
const char *ptr = (const char *)_datagram->get_data();
size_t remaining_size = _datagram->get_length() - _current_index;
return string(ptr + _current_index, remaining_size);
const unsigned char *ptr = (const unsigned char *)_datagram->get_data();
return vector_uchar(ptr + _current_index, ptr + _datagram->get_length());
}
/**

View File

@ -119,18 +119,18 @@ get_wstring() {
* Extracts the indicated number of bytes in the datagram and returns them as
* a string.
*/
string DatagramIterator::
vector_uchar DatagramIterator::
extract_bytes(size_t size) {
nassertr((int)size >= 0, "");
nassertr(_datagram != (const Datagram *)NULL, "");
nassertr(_current_index + size <= _datagram->get_length(), "");
nassertr((int)size >= 0, vector_uchar());
nassertr(_datagram != (const Datagram *)NULL, vector_uchar());
nassertr(_current_index + size <= _datagram->get_length(), vector_uchar());
const char *ptr = (const char *)_datagram->get_data();
size_t last_index = _current_index;
const unsigned char *ptr = (const unsigned char *)_datagram->get_data();
ptr += _current_index;
_current_index += size;
return string(ptr + last_index, size);
return vector_uchar(ptr, ptr + size);
}
/**

View File

@ -62,10 +62,10 @@ PUBLISHED:
wstring get_wstring();
INLINE void skip_bytes(size_t size);
string extract_bytes(size_t size);
vector_uchar extract_bytes(size_t size);
size_t extract_bytes(unsigned char *into, size_t size);
INLINE string get_remaining_bytes() const;
INLINE vector_uchar get_remaining_bytes() const;
INLINE size_t get_remaining_size() const;
INLINE const Datagram &get_datagram() const;

View File

@ -143,11 +143,11 @@ set_from_hex(const string &text) {
/**
* Returns the HashVal as a 16-byte binary string.
*/
string HashVal::
vector_uchar HashVal::
as_bin() const {
Datagram dg;
write_datagram(dg);
return dg.get_message();
return vector_uchar((unsigned char *)dg.get_data(), (unsigned char *)dg.get_data() + dg.get_length());
}
/**
@ -155,7 +155,7 @@ as_bin() const {
* false otherwise.
*/
bool HashVal::
set_from_bin(const string &text) {
set_from_bin(const vector_uchar &text) {
nassertr(text.size() == 16, false);
Datagram dg(text);
DatagramIterator dgi(dg);

View File

@ -55,8 +55,8 @@ PUBLISHED:
string as_hex() const;
bool set_from_hex(const string &text);
string as_bin() const;
bool set_from_bin(const string &text);
vector_uchar as_bin() const;
bool set_from_bin(const vector_uchar &text);
INLINE void write_datagram(Datagram &destination) const;
INLINE void read_datagram(DatagramIterator &source);

View File

@ -2402,7 +2402,7 @@ check_signatures() {
nassertv(stream != NULL);
StreamReader reader(*stream);
size_t sig_size = reader.get_uint32();
string sig_string = reader.extract_bytes(sig_size);
vector_uchar sig_data = reader.extract_bytes(sig_size);
size_t num_certs = reader.get_uint32();
@ -2470,9 +2470,7 @@ check_signatures() {
// Now check that the signature matches the hash.
int verify_result =
EVP_VerifyFinal(md_ctx,
(unsigned char *)sig_string.data(),
sig_string.size(), pkey);
EVP_VerifyFinal(md_ctx, sig_data.data(), sig_data.size(), pkey);
if (verify_result == 1) {
// The signature matches; save the certificate and its chain.
_signatures.push_back(chain);

View File

@ -92,6 +92,19 @@ PointerToArray(PointerToArray<Element> &&from) NOEXCEPT :
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
* Initializes the PTA from a vector.
*/
template<class Element>
INLINE PointerToArray<Element>::
PointerToArray(pvector<Element> &&from, TypeHandle type_handle) :
PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(move(from))),
_type_handle(type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
/**
*
*/
@ -710,6 +723,19 @@ ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT :
}
#endif // USE_MOVE_SEMANTICS
#ifdef USE_MOVE_SEMANTICS
/**
* Initializes the PTA from a vector.
*/
template<class Element>
INLINE ConstPointerToArray<Element>::
ConstPointerToArray(pvector<Element> &&from, TypeHandle type_handle) :
PointerToArrayBase<Element>(new ReferenceCountedVector<Element>(move(from))),
_type_handle(type_handle)
{
}
#endif // USE_MOVE_SEMANTICS
/**
*
*/

View File

@ -141,6 +141,7 @@ public:
#ifdef USE_MOVE_SEMANTICS
INLINE PointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE explicit PointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
#endif
public:
@ -302,6 +303,7 @@ PUBLISHED:
#ifdef USE_MOVE_SEMANTICS
INLINE ConstPointerToArray(PointerToArray<Element> &&from) NOEXCEPT;
INLINE ConstPointerToArray(ConstPointerToArray<Element> &&from) NOEXCEPT;
INLINE explicit ConstPointerToArray(pvector<Element> &&from, TypeHandle type_handle = get_type_handle(Element));
#endif
// Duplicating the interface of vector.

View File

@ -39,6 +39,16 @@ ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type
{
}
/**
* Creates an array that takes its elements from the given vector.
*/
template<class Element>
INLINE ReferenceCountedVector<Element>::
ReferenceCountedVector(pvector<Element> &&from) :
pvector<Element>(move(from))
{
}
/**
*
*/

View File

@ -43,6 +43,7 @@ public:
INLINE ReferenceCountedVector(TypeHandle type_handle);
INLINE ReferenceCountedVector(size_type initial_size, TypeHandle type_handle);
INLINE ReferenceCountedVector(const Element *begin, const Element *end, TypeHandle type_handle);
INLINE ReferenceCountedVector(pvector<Element> &&from);
ALLOC_DELETED_CHAIN(ReferenceCountedVector<Element>);
INLINE size_type size() const;

View File

@ -4207,7 +4207,9 @@ bool Texture::
do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only) {
StreamReader ktx(in);
if (ktx.extract_bytes(12) != "\xABKTX 11\xBB\r\n\x1A\n") {
unsigned char magic[12];
if (ktx.extract_bytes(magic, 12) != 12 ||
memcmp(magic, "\xABKTX 11\xBB\r\n\x1A\n", 12) != 0) {
gobj_cat.error()
<< filename << " is not a KTX file.\n";
return false;

View File

@ -106,7 +106,8 @@ WavAudioCursor(WavAudio *src, istream *stream) :
nassertv(stream != NULL);
// Beginning of "RIFF" chunk.
if (_reader.extract_bytes(4) != "RIFF") {
unsigned char magic[4];
if (_reader.extract_bytes(magic, 4) != 4 || memcmp(magic, "RIFF", 4) != 0) {
movies_cat.error()
<< ".wav file is not a valid RIFF file.\n";
return;
@ -114,7 +115,7 @@ WavAudioCursor(WavAudio *src, istream *stream) :
unsigned int chunk_size = _reader.get_uint32();
if (_reader.extract_bytes(4) != "WAVE") {
if (_reader.extract_bytes(magic, 4) != 4 || memcmp(magic, "WAVE", 4) != 0) {
movies_cat.error()
<< ".wav file is a RIFF file but does not start with a WAVE chunk.\n";
return;
@ -126,10 +127,10 @@ WavAudioCursor(WavAudio *src, istream *stream) :
while ((!have_fmt || !have_data) && _stream->good() && (bytes_read + 8) < chunk_size) {
string subchunk_id = _reader.extract_bytes(4);
_reader.extract_bytes(magic, 4);
unsigned int subchunk_size = _reader.get_uint32();
if (subchunk_id == "fmt ") {
if (memcmp(magic, "fmt ", 4) == 0) {
// The format chunk specifies information about the storage.
nassertv(subchunk_size >= 16);
have_fmt = true;
@ -202,7 +203,7 @@ WavAudioCursor(WavAudio *src, istream *stream) :
_reader.skip_bytes(subchunk_size - read_bytes);
}
} else if (subchunk_id == "data") {
} else if (memcmp(magic, "data", 4) == 0) {
// The data chunk contains the actual sammples.
if (!have_fmt) {
movies_cat.error()

View File

@ -82,8 +82,10 @@ play_frame(DatagramIterator &scan, BamReader *manager) {
int num_packets = scan.get_uint16();
for (int i = 0; i < num_packets; i++) {
string packet = scan.get_string();
_data.push_back(Datagram(packet));
size_t size = scan.get_uint16();
vector_uchar packet(size);
scan.extract_bytes(&packet[0], size);
_data.push_back(Datagram(move(packet)));
}
}

View File

@ -78,9 +78,8 @@ extract_record(FltRecordReader &reader) {
bool FltBeadID::
extract_ancillary(FltRecordReader &reader) {
if (reader.get_opcode() == FO_long_id) {
string s = reader.get_iterator().get_remaining_bytes();
size_t zero_byte = s.find('\0');
_id = s.substr(0, zero_byte);
vector_uchar s = reader.get_iterator().get_remaining_bytes();
_id.assign((const char *)s.data(), strnlen((const char *)s.data(), s.size()));
return true;
}
@ -109,14 +108,11 @@ build_record(FltRecordWriter &writer) const {
FltError FltBeadID::
write_ancillary(FltRecordWriter &writer) const {
if (_id.length() > 7) {
Datagram dc;
// Although the manual mentions nothing of this, it is essential that the
// length of the record be a multiple of 4 bytes.
string id = _id;
while ((id.length() % 4) != 0) {
id += '\0';
}
Datagram dc(id);
dc.add_fixed_string(_id, (_id.length() + 3) & ~3);
FltError result = writer.write_record(FO_long_id, dc);
if (result != FE_ok) {

View File

@ -621,7 +621,8 @@ extract_record(FltRecordReader &) {
bool FltRecord::
extract_ancillary(FltRecordReader &reader) {
if (reader.get_opcode() == FO_comment) {
_comment = reader.get_iterator().get_remaining_bytes();
vector_uchar s = reader.get_iterator().get_remaining_bytes();
_comment.assign((const char *)s.data(), strnlen((const char *)s.data(), s.size()));
return true;
}
@ -735,7 +736,7 @@ build_record(FltRecordWriter &) const {
FltError FltRecord::
write_ancillary(FltRecordWriter &writer) const {
if (!_comment.empty()) {
Datagram dc(_comment);
Datagram dc(_comment.data(), _comment.size());
FltError result = writer.write_record(FO_comment, dc);
if (result != FE_ok) {
return result;