This commit is contained in:
Demi Marie Obenour 2023-06-03 18:39:05 -04:00
parent cb9e1f4244
commit 6d965bf6c1
2 changed files with 63 additions and 27 deletions

View File

@ -881,7 +881,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
code_lines, temp_vars, code_lines, temp_vars,
space, prefix): space, prefix):
count = 0 count = 0
switch_expr = _c_accessor_get_expr(self.expr, None, False) switch_expr = _c_accessor_get_expr(self.expr, None, context.endswith('checked'))
for b in self.bitcases: for b in self.bitcases:
len_expr = len(b.type.expr) len_expr = len(b.type.expr)
@ -893,7 +893,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
compare_operator = '&' compare_operator = '&'
for n, expr in enumerate(b.type.expr): for n, expr in enumerate(b.type.expr):
bitcase_expr = _c_accessor_get_expr(expr, None, False) bitcase_expr = _c_accessor_get_expr(expr, None, context.endswith('checked'))
# only one <enumref> in the <bitcase> # only one <enumref> in the <bitcase>
if len_expr == 1: if len_expr == 1:
code_lines.append( code_lines.append(
@ -1029,7 +1029,7 @@ def _c_serialize_helper_list_field(context, self, field,
if expr.op == 'calculate_len': if expr.op == 'calculate_len':
list_length = field.type.expr.lenfield_name list_length = field.type.expr.lenfield_name
else: else:
list_length = _c_accessor_get_expr(expr, field_mapping, False) list_length = _c_accessor_get_expr(expr, field_mapping, context.endswith('checked'))
# default: list with fixed size elements # default: list with fixed size elements
length = 'xcb_checked_mul(%s, sizeof(%s))' % (list_length, field.type.member.c_wiretype) length = 'xcb_checked_mul(%s, sizeof(%s))' % (list_length, field.type.member.c_wiretype)
@ -1367,7 +1367,7 @@ def _c_serialize_helper(context, complex_type,
count += _c_serialize_helper_fields(context, self, count += _c_serialize_helper_fields(context, self,
code_lines, temp_vars, code_lines, temp_vars,
space, prefix, False) space, prefix, context.endswith('checked'))
# "final padding" # "final padding"
count += _c_serialize_helper_insert_padding(context, complex_type, code_lines, space, False, self.is_switch) count += _c_serialize_helper_insert_padding(context, complex_type, code_lines, space, False, self.is_switch)
@ -1743,7 +1743,6 @@ def _c_accessor_get_expr(expr, field_mapping, checked):
Otherwise, uses the value of the length field. Otherwise, uses the value of the length field.
''' '''
lenexp = _c_accessor_get_length(expr, field_mapping) lenexp = _c_accessor_get_length(expr, field_mapping)
if expr.op == '~': # SAFE if expr.op == '~': # SAFE
return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping, checked) + ')' return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping, checked) + ')'
elif expr.op == 'popcount': # SAFE elif expr.op == 'popcount': # SAFE
@ -1822,9 +1821,39 @@ def _c_accessor_get_expr(expr, field_mapping, checked):
elif expr.op == 'listelement-ref': elif expr.op == 'listelement-ref':
return '(*xcb_listelement)' return '(*xcb_listelement)'
elif expr.op != None and expr.op != 'calculate_len': elif expr.op != None and expr.op != 'calculate_len':
return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping, checked) + _c_pre.start()
' ' + expr.op + ' ' + sumvar = _c_pre.get_tempvarname()
_c_accessor_get_expr(expr.rhs, field_mapping, checked) + ')') match expr.op:
case '+':
op = 'add'
case '-':
op = 'sub'
case '*':
op = 'mul'
case '/':
_c_pre.tempvar("int64_t %s;", sumvar)
_c_pre.code("%s = (%s);",
sumvar,
_c_accessor_get_expr(expr.rhs, field_mapping, checked))
_c_pre.code("if (%s < 1)", sumvar)
_c_pre.code(" return -1;" if checked else " abort();")
_c_pre.end()
return ('((' + _c_accessor_get_expr(expr.lhs, field_mapping, checked) + ') / ' + sumvar + ')')
case '&':
_c_pre.end()
return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping, checked) +
' & ' + _c_accessor_get_expr(expr.rhs, field_mapping, checked) + ')')
case _:
assert False
_c_pre.tempvar("int64_t %s; /* sum */", sumvar)
_c_pre.code("if (__builtin_%s_overflow((%s), (%s), &%s))",
op,
_c_accessor_get_expr(expr.lhs, field_mapping, checked),
_c_accessor_get_expr(expr.rhs, field_mapping, checked),
sumvar)
_c_pre.code(" return -1;" if checked else " abort();")
_c_pre.end()
return ('(' + sumvar + ')')
elif expr.bitfield: elif expr.bitfield:
return 'xcb_popcount(' + lenexp + ')' return 'xcb_popcount(' + lenexp + ')'
else: else:
@ -2137,10 +2166,9 @@ def _c_accessors(self, name, base):
''' '''
# no accessors for switch itself - # no accessors for switch itself -
# switch always needs to be unpacked explicitly # switch always needs to be unpacked explicitly
# if self.is_switch: if self.is_switch:
# pass assert False
# else: else:
if True:
for field in self.fields: for field in self.fields:
if not field.type.is_pad: if not field.type.is_pad:
if _c_field_needs_list_accessor(field): if _c_field_needs_list_accessor(field):

View File

@ -30,9 +30,7 @@
#endif #endif
#include <assert.h> #include <assert.h>
#if __STDC_VERSION__ >= 201112L
#include <stdalign.h> #include <stdalign.h>
#endif
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -241,12 +239,16 @@ static int read_setup(xcb_connection_t *c)
* Padded length of the vendor string. setup->vendor_len is a * Padded length of the vendor string. setup->vendor_len is a
* uint16_t so overflow is impossible. Cannot exceed 65536. * uint16_t so overflow is impossible. Cannot exceed 65536.
*/ */
static_assert(sizeof(setup->vendor_len) == 2,
"wrong size of setup->vendor_len");
uint32_t const pixmap_offset = (setup->vendor_len + UINT32_C(3)) & ~UINT32_C(3); uint32_t const pixmap_offset = (setup->vendor_len + UINT32_C(3)) & ~UINT32_C(3);
/* /*
* Length of the pixmap formats. setup->pixmap_formats_len is * Length of the pixmap formats. setup->pixmap_formats_len is
* uint8_t so overflow is impossible. * uint8_t so overflow is impossible.
*/ */
static_assert(sizeof(setup->pixmap_formats_len) == 1,
"wrong size of setup->pixmap_formats_len");
uint32_t const pixmap_formats_len = sizeof(xcb_format_t) * setup->pixmap_formats_len; uint32_t const pixmap_formats_len = sizeof(xcb_format_t) * setup->pixmap_formats_len;
/* Offset of the screens. Max RHS = 40 + 65536 + 8 * 255 = 67616 so no risk of overflow */ /* Offset of the screens. Max RHS = 40 + 65536 + 8 * 255 = 67616 so no risk of overflow */
@ -255,20 +257,24 @@ static int read_setup(xcb_connection_t *c)
/* 4 zero bytes, for memcmp() */ /* 4 zero bytes, for memcmp() */
uint32_t const zero = 0; uint32_t const zero = 0;
#if __STDC_VERSION__ >= 201112L
/* A bunch of static assertions */ /* A bunch of static assertions */
static_assert(sizeof(xcb_screen_t) == 40, "bug"); #define ASSERT_SIZE_ALIGN(t, size, align) \
static_assert(sizeof(xcb_setup_t) == 40, "bug"); do { \
static_assert(sizeof(xcb_setup_generic_t) == 8, "bug"); static_assert(sizeof(t) == size, \
static_assert(sizeof(xcb_setup_authenticate_t) == 8, "bug"); "unexpected size of" #t); \
static_assert(sizeof(xcb_setup_failed_t) == 8, "bug"); static_assert(alignof(t) == align, \
static_assert(sizeof(xcb_visualtype_t) == 24, "bug"); "unexpected alignment of" #t); \
static_assert(sizeof(xcb_depth_t) == 8, "bug"); } while (0);
static_assert(sizeof(xcb_format_t) == 8, "bug"); ASSERT_SIZE_ALIGN(xcb_screen_t, 40, 4);
static_assert(alignof(xcb_screen_t) == 4, "bug"); ASSERT_SIZE_ALIGN(xcb_setup_t, 40, 4);
static_assert(alignof(xcb_visualtype_t) == 4, "bug"); ASSERT_SIZE_ALIGN(xcb_setup_generic_t, 8, 2);
static_assert(alignof(xcb_depth_t) == 2, "bug"); ASSERT_SIZE_ALIGN(xcb_setup_authenticate_t, 8, 2);
#endif ASSERT_SIZE_ALIGN(xcb_setup_failed_t, 8, 2);
ASSERT_SIZE_ALIGN(xcb_visualtype_t, 24, 4);
ASSERT_SIZE_ALIGN(xcb_depth_t, 8, 2);
ASSERT_SIZE_ALIGN(xcb_format_t, 8, 1);
#undef ASSERT_SIZE_ALIGN
/* Must have at least 1 screen and 1 pixmap format */ /* Must have at least 1 screen and 1 pixmap format */
if (setup->roots_len < 1 || setup->pixmap_formats_len < 1) if (setup->roots_len < 1 || setup->pixmap_formats_len < 1)
return 0; return 0;
@ -348,6 +354,8 @@ static int read_setup(xcb_connection_t *c)
return 0; return 0;
/* depth->visuals_len is uint16_t so overflow is impossible. */ /* depth->visuals_len is uint16_t so overflow is impossible. */
static_assert(sizeof(depth->visuals_len) == 2,
"wrong size of setup->visuals_len");
visuals_size = (uint32_t)depth->visuals_len * sizeof(*visuals); visuals_size = (uint32_t)depth->visuals_len * sizeof(*visuals);
/* Visuals must fit in the buffer. */ /* Visuals must fit in the buffer. */