From 0ed48e7c4e6e5fca963399cb79fe4870f328e7f9 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Thu, 15 Aug 2024 10:11:00 -0400 Subject: [PATCH] Don't insert padding between lists in requests Lists of types that have the same padding as each other should not have any padding automatically inserted by libxcb. Fixes xcb_randr_set_crtc_gamma when "size" is an odd number. Requires us to loop over all the fields, not just the param fields, so that we can generate code for (which was previously missing, but went unnoticed because libxcb was always behaving as if a was present between each list). Incidentally reduces the number of unnecessary pad entries in the xcb_parts lists (eg. between lists when the first is a list of CARD32). Signed-off-by: Peter Harris --- src/c_client.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/c_client.py b/src/c_client.py index b7db543..cd32c2e 100644 --- a/src/c_client.py +++ b/src/c_client.py @@ -2336,13 +2336,14 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False): spacing, c_pointer, field.c_field_name, comma) count = 2 + need_end_pad = False if not self.c_var_followed_by_fixed_fields: - for field in param_fields: + for field in self.fields: if not field.type.fixed_size() and field.wire: - count = count + 2 - if field.type.c_need_serialize or field.type.c_need_sizeof: - # _serialize() keeps track of padding automatically - count -= 1 + count += 1 + need_end_pad = True + if need_end_pad: + count += 1 dimension = count + 2 _c('{') @@ -2426,11 +2427,14 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False): count = 4 - for field in param_fields: + for field in self.fields: if field.wire and not field.type.fixed_size(): _c(' /* %s %s */', field.type.c_type, field.c_field_name) - # default: simple cast to char * - if not field.type.c_need_serialize and not field.type.c_need_sizeof: + if field.type.is_pad and field.type.align > 1: + _c(' xcb_parts[%d].iov_base = 0;', count) + _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & %d;', count, count-1, field.type.align-1) + elif not field.type.c_need_serialize and not field.type.c_need_sizeof: + # default: simple cast to char * _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name) if field.type.is_list: if field.type.member.fixed_size(): @@ -2474,11 +2478,15 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False): _c(' %s (%s);', func_name, serialize_args) count += 1 - if not (field.type.c_need_serialize or field.type.c_need_sizeof): - # the _serialize() function keeps track of padding automatically - _c(' xcb_parts[%d].iov_base = 0;', count) - _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1) - count += 1 + if need_end_pad: + _c(' xcb_parts[%d].iov_base = 0;', count) + if count == 5: + _c(' xcb_parts[%d].iov_len = -xcb_parts[4].iov_len & 3;', count) + else: + parts = [] + for part in range(4, count): + parts.append("xcb_parts[%d].iov_len" % part) + _c(' xcb_parts[%d].iov_len = -(%s) & 3;', count, ' + '.join(parts)) # elif self.c_var_followed_by_fixed_fields: else: