Sending / Receiving of byte arrays

Simon McVittie simon.mcvittie at collabora.co.uk
Wed Feb 8 01:48:41 PST 2012


On 07/02/12 22:24, Bogdan Lotko wrote:
> In the following (C++) structure the *buff *shall be sent as a byte array
...
> I suppose the signature will be something like (sia(yyyy)), and I have
> to send all bytes separately, or there is a better way to do it

(Disclaimer: I understand D-Bus, but I haven't used Qt for a while.)

Think about what you want to achieve on D-Bus, *then* about how to get
that to happen in QtDBus. Do you want the signature to be (siay) or
(si(yyyy)) or (siyyyy), or even (siu)? Any of those are achievable - the
right one depends on what those four bytes represent.

I suspect the answer is probably that you want (siay), but I could be
wrong - it depends what the bytes represent, and you haven't really
given enough context for a good guess.

If you want (si(yyyy)) or (siyyyy), you'll have to serialize each of the
four bytes separately (it's a special case of a struct); if you want
(siu) you'll have to combine the bytes into an unsigned int and send that.

> I've also been thinking to use the structure with  QByteArray instead
> of  *buff.  *Is it feasible?
>  e.g construct the QByteArray using  fromRawData(buff,4)  just before
> sending.

That's how I'd do it: I believe QtDBus already knows how to send a
QByteArray as an 'ay', so construct a temporary one from buff and
serialize that with the << operator. (But use sizeof(myStruct.buff)
instead of hard-coding 4.)

> How to receive this byte array ( there is nothing like "toRawData()" ) ?

You can deserialize an 'ay' into a temporary QByteArray with the >>
operator. After that, there are three situations you need to think about:

* the other process sends the right amount of data
* the other process sends too much data
* the other process sends too little data

Possible resolutions for "too much data" include returning an error to
the other process, or silently truncating at 4 bytes. Possible
resolutions for "too little data" include returning an error to the
other process, or padding with zeroes. Don't let the other process
overflow the buffer and trigger a remote exploit... and you probably
don't want to be using uninitialized data if it provides too little, either.

Here's one possible implementation of truncation and zero-padding:

    std::memset(myStruct.buff, '\0', sizeof(myStruct.buff));
    std::memcpy(myStruct.buff, myByteArray.constData(),
                MIN(myByteArray.size(), sizeof(myStruct.buff)));

but to be honest I'm not sure why you're using a fixed-size char[n] in
Qt/C++ code at all - if you can just put a QByteArray in the struct,
you'll be much better-protected from buffer overflows. (Similarly, I'd
be inclined to use a GByteArray or a GString if this was GLib code.)

    S


More information about the dbus mailing list