The body code didn't use atomic loads, so it had undefined behavior if
the body was concurrently modified. Use atomic loads to fix this.
Since the memory order is __ATOMIC_RELAXED this has no runtime overhead.
Also add barriers around a strncpy call and cast to volatile before
checking for a NUL terminator, though NUL-terminated strings in shared
memory are unuseable. There are some places where bytewise atomic
memcpy(), which doesn't currently exist, is needed. Instead, try to
fake it by using two barriers around memcpy().
Make one COLLECT function that always reads all the varargs (SKIP)
and then tries to collect the pod+body with type checks
(can_collect + COLLECT). This makes things nicer because we can do
everything in one go and we only do one type check.
This partially reverts commit f7ae61cb1e.
We do want to do the checks in spa_pod_body_get_*() for extra safety.
The reason they were removed is because then we do the checks twice in
the parser. It should however be possible to fuse the can_collect and
COLLECT and SKIP calls together in the future.
We need to be sure that the compiler does not perform invented loads
after we checked the pod size. Otherwise we could have found that the
size was ok, only to be overwritten by an invalid size.
One way of avoiding this is to surround the memcpy with a barrier.
See #4822
Make a new body.h file with some functions to deal with pod and their
body. Make the iter.h functions use mostly this.
Rework the parser so that it only uses body.h functions. With the separation
of pod+body, we can read and verify the pod once and then use the
verified copy to handle the rest of the body safely.
We do this because iter.h only works in pods in memory that doesn't change
because it is vulnerable to modifications of the data after verifying it.
The new parser is not vulnerable to this and will not cause invalid
memory access when used on shared memory. There is however no need for
atomic operations to read the headers, whever is read is either valid
and useable of invalid and rejected.
See #4822
Use get_string() to get a pointer to the string in the pod so that we
also check if it has a 0 terminator.
Fix the test case now that is_string returns true even for non
zero-terminated strings.
The _is_type() macros should simply check the type in the header and if
the size is large enough to look into the type specifics. Further
validation of the values should be done when the value is retrieved.
Following this logic, the String zero byte check should be done in the
get_string() function.
We already know that we could succesfully allocate enough space for the
bytes because we checked that before so simply move to the body of the
new bytes pod. We don't need to do the extensive checks we do in deref.
Add a function that can build a pod from a pod definition, a body data
and a suffix.
We can use this to build strings and bytes and arrays like the other
primitives, which makes it possible to add them to choices or arrays.
Fixes#4588
Use the area to compare two rectangles. Use the width to break a tie.
This way the sorting is at least a bit more predictable and independent
of the order of the arguments.
Disable the padding to pod alignment for everything when we are building
the body of an array or choice.
This makes it possible to use bytes or strings or any other pod of a
fixed size as entries in arrays or choice.
Assume that all the functions that take a type/size/data from a pod have
at least the right number of bytes in the data for the given type.
Callers need to ensure this.
Fix the callers of such functions to always make sure they deref a pod
type/size/body into something of at least the min size of the type.
Do a more thorough test of the choice type by not only checking the type
but also if the size is at least large enough to be able to cast it to
the pod_choice type and look at the contents.
In the filter, don't _deref or use _frame before we are going to add
more pods to the builder. If we are using a dynamic builder, the
dereffed pod might become invalid when the memory is reallocated.
Instead, take the offset of the frame and deref later when we are not
going to add more things.
Add the missing type info for:
* SPA_FORMAT_VIDEO_colorRange
* SPA_FORMAT_VIDEO_colorMatrix
* SPA_FORMAT_VIDEO_transferFunction
* SPA_FORMAT_VIDEO_colorPrimaries
We currently often create pods in a uint8_t buffer, which is not aligned
to 8 and might cause deref and other problems.
We should either align the buffer we write into or maybe make the
builder add some padding before the buffer to align it. We have to be
careful with that when we assume the buffer start is the beginning of
the pod..
Fixes#4794
Previously, custom object properties were printed as "unknown",
and the offset (wrt. `SPA_PROP_START_CUSTOM`) was not displayed.
A custom property is distinct from an "unknown" one. Being able
to quickly differentiate the two is useful. Furthermore, knowing
the custom property id (i.e. the actual numeric id minus
`SPA_PROP_START_CUSTOM`) is also very helpful.
To address the above, print a custom property (i.e. anything with
an id at least `SPA_PROP_START_CUSTOM`) as follows:
Spa:Pod:Object:Param:Props:Custom:123
where the last component is the custom property id.
Make a new function to also returnt he child size and type.
Make a new function that accepts the array item size. Check that the
array item size and destination item size match before memcpy the array
contents. This avoids overflowing the target array with a malformed
array pod.
For the embedded children, they will always be aligned. We can also
avoid the max size checks for children because this is already checked
for the parent and with the remaining size check.
For arrays and choice we simply don't get any elements in the array when
the sizes are too large.
We don't really want to do this here otherwise structs that include a
pod will be padded so that an array of those structs will be aligned.
This makes a test case fail where we have a struct with a choice_body
followed by 3 uint32_t enum values. The size with and without the
aligned attribute is different.