(CVE-2023-32665) GVariant deserialisation does not match spec for non-normal data
I've been writing an implementation of the GVariant serialisation format in Rust against the GVariant spec found here: https://people.gnome.org/~desrt/gvariant-serialisation.pdf . To test it I've been fuzzing my implementation and the GLib one and comparing outputs. I've come across a couple of cases where I don't think the GLib implementation matches the GVariant spec when interpreting non-normal data.
Firstly strings:
The spec gives the example:
String with Embedded Nul
With type 's':
'f 'o 'o \0 'b 'a 'r \0
has a value of
'foo'
.
because
2.7.3 Handling Non-Normal Serialised Data
String with Embedded Nul
If a string has a nul character as its final byte, but also contains another nul character before this final terminator, the value of the string is taken to be the part of the string that precedes the embedded nul. This means that obtaining a C pointer to a string is still a constant time operation.
Whereas the GLib implementation interprets it as an empty string.
Secondly non-fixed width arrays:
With typestring aay GLib interprets
01 00
as [[], []]
whereas I think the spec requires [[1], []]
. There are two items because 00
says that the start of the frame-offsets is at index 0. The first item is bytes 0..1
and the second item is bytes 1..0
.
So the first item gets the value [1]
, even though it overlaps the framing offsets. Spec says:
Child Values Overlapping Framing Offsets
If the byte sequence of a child value overlaps the framing offsets of the container it resides within then this error is ignored. The child is given a value that corresponds to the normal deserialisation process performed on this byte sequence (including the bytes from the framing offsets) with the type of the child.
I think either the GLib implementation or the spec should be updated to resolve this inconsistency.
See my GVariant implementation here: https://github.com/wmanley/gvariant-rs and specifically the fuzzing bit here: https://github.com/wmanley/gvariant-rs/blob/master/fuzz/fuzz_targets/fuzz_target_1.rs