Add even more bounds checks
This adds checked _sizeof(), _unpack(), and _unserialize() functions.
This commit is contained in:
parent
0035d2673d
commit
9f0edb0b54
147
src/c_client.py
147
src/c_client.py
|
@ -308,6 +308,13 @@ def c_open(self):
|
||||||
|
|
||||||
_c('')
|
_c('')
|
||||||
_c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
|
_c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
|
||||||
|
_c('static int xcb_checked_mul(unsigned long long x, unsigned long long y)')
|
||||||
|
_c('{')
|
||||||
|
_c(' int z;')
|
||||||
|
_c(' if (__builtin_mul_overflow(x, y, &z))')
|
||||||
|
_c(' return -1;')
|
||||||
|
_c(' return z;')
|
||||||
|
_c('}')
|
||||||
|
|
||||||
def c_close(self):
|
def c_close(self):
|
||||||
'''
|
'''
|
||||||
|
@ -528,12 +535,14 @@ def _c_type_setup(self, name, postfix):
|
||||||
# special cases -> unserialize
|
# special cases -> unserialize
|
||||||
if self.is_switch or self.c_var_followed_by_fixed_fields:
|
if self.is_switch or self.c_var_followed_by_fixed_fields:
|
||||||
_c_serialize('unserialize', self)
|
_c_serialize('unserialize', self)
|
||||||
|
_c_serialize('unserialize_checked', self)
|
||||||
|
|
||||||
if self.c_need_sizeof:
|
if self.c_need_sizeof:
|
||||||
if self.c_sizeof_name not in finished_sizeof:
|
if self.c_sizeof_name not in finished_sizeof:
|
||||||
if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
|
if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
|
||||||
finished_sizeof.append(self.c_sizeof_name)
|
finished_sizeof.append(self.c_sizeof_name)
|
||||||
_c_serialize('sizeof', self)
|
_c_serialize('sizeof', self)
|
||||||
|
_c_serialize('sizeof_checked', self)
|
||||||
|
|
||||||
# Functions for querying field properties
|
# Functions for querying field properties
|
||||||
def _c_field_needs_list_accessor(field):
|
def _c_field_needs_list_accessor(field):
|
||||||
|
@ -791,8 +800,12 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
|
||||||
# 1. the parameter for the void * buffer
|
# 1. the parameter for the void * buffer
|
||||||
if 'serialize' == context:
|
if 'serialize' == context:
|
||||||
params.append(('void', '**', buffer_var))
|
params.append(('void', '**', buffer_var))
|
||||||
elif context in ('unserialize', 'unpack', 'sizeof'):
|
elif context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked', 'sizeof', 'sizeof_checked'):
|
||||||
params.append(('const void', '*', buffer_var))
|
params.append(('const void', '*', buffer_var))
|
||||||
|
if context.endswith('checked'):
|
||||||
|
params.append(('const void', '*', 'xcb_end'))
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
# 2. any expr fields that cannot be resolved within self and descendants
|
# 2. any expr fields that cannot be resolved within self and descendants
|
||||||
unresolved_fields = resolve_expr_fields(self)
|
unresolved_fields = resolve_expr_fields(self)
|
||||||
|
@ -815,9 +828,9 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
|
||||||
# 4. aux argument
|
# 4. aux argument
|
||||||
if 'serialize' == context:
|
if 'serialize' == context:
|
||||||
add_param(params, ('const %s' % self.c_type, '*', aux_var))
|
add_param(params, ('const %s' % self.c_type, '*', aux_var))
|
||||||
elif 'unserialize' == context:
|
elif context.startswith('unserialize'):
|
||||||
add_param(params, ('%s' % self.c_type, '**', aux_var))
|
add_param(params, ('%s' % self.c_type, '**', aux_var))
|
||||||
elif 'unpack' == context:
|
elif context.startswith('unpack'):
|
||||||
add_param(params, ('%s' % self.c_type, '*', aux_var))
|
add_param(params, ('%s' % self.c_type, '*', aux_var))
|
||||||
|
|
||||||
# 5. switch contains all variable size fields as struct members
|
# 5. switch contains all variable size fields as struct members
|
||||||
|
@ -849,7 +862,9 @@ def _c_serialize_helper_insert_padding(context, complex_type, code_lines, space,
|
||||||
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
|
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
|
||||||
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
|
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
|
||||||
code_lines.append('%s xcb_parts_idx++;' % space)
|
code_lines.append('%s xcb_parts_idx++;' % space)
|
||||||
elif context in ('unserialize', 'unpack', 'sizeof'):
|
elif context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked', 'sizeof', 'sizeof_checked'):
|
||||||
|
if context.endswith('checked'):
|
||||||
|
_c_emit_bounds_check(code_lines, space + ' ', 'xcb_pad')
|
||||||
code_lines.append('%s xcb_tmp += xcb_pad;' % space)
|
code_lines.append('%s xcb_tmp += xcb_pad;' % space)
|
||||||
|
|
||||||
code_lines.append('%s xcb_pad = 0;' % space)
|
code_lines.append('%s xcb_pad = 0;' % space)
|
||||||
|
@ -907,7 +922,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
|
||||||
|
|
||||||
# if 'serialize' == context:
|
# if 'serialize' == context:
|
||||||
# count += _c_serialize_helper_insert_padding(context, self, code_lines, space, False)
|
# count += _c_serialize_helper_insert_padding(context, self, code_lines, space, False)
|
||||||
# elif context in ('unserialize', 'unpack', 'sizeof'):
|
# elif context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked', 'sizeof', 'sizeof_checked'):
|
||||||
# # padding
|
# # padding
|
||||||
# code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
|
# code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
|
||||||
# code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
|
# code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
|
||||||
|
@ -946,13 +961,16 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
|
||||||
if 'serialize' == context:
|
if 'serialize' == context:
|
||||||
length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
|
length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
|
||||||
c_field_names, prefix_str, field.c_field_name)
|
c_field_names, prefix_str, field.c_field_name)
|
||||||
elif context in ('unserialize', 'unpack'):
|
elif context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked'):
|
||||||
length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
|
length = "%s%s(xcb_tmp, %s%s&%s%s)" % (field.type.c_unpack_name, '_checked' if context.endswith('checked') else '',
|
||||||
c_field_names, prefix_str, field.c_field_name)
|
'xcb_end, ' if context.endswith('checked') else '',
|
||||||
elif 'sizeof' == context:
|
c_field_names, prefix_str, field.c_field_name)
|
||||||
|
elif context in ('sizeof', 'sizeof_checked'):
|
||||||
# remove trailing ", " from c_field_names because it will be used at end of arglist
|
# remove trailing ", " from c_field_names because it will be used at end of arglist
|
||||||
my_c_field_names = c_field_names[:-2]
|
my_c_field_names = c_field_names[:-2]
|
||||||
length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
|
length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
|
||||||
|
else:
|
||||||
|
assert False, 'bad context %r' % context
|
||||||
|
|
||||||
return length
|
return length
|
||||||
|
|
||||||
|
@ -1014,7 +1032,7 @@ def _c_serialize_helper_list_field(context, self, field,
|
||||||
list_length = _c_accessor_get_expr(expr, field_mapping)
|
list_length = _c_accessor_get_expr(expr, field_mapping)
|
||||||
|
|
||||||
# default: list with fixed size elements
|
# default: list with fixed size elements
|
||||||
length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
|
length = 'xcb_checked_mul(%s, sizeof(%s))' % (list_length, field.type.member.c_wiretype)
|
||||||
|
|
||||||
# list with variable-sized elements
|
# list with variable-sized elements
|
||||||
if not field.type.member.fixed_size():
|
if not field.type.member.fixed_size():
|
||||||
|
@ -1027,7 +1045,7 @@ def _c_serialize_helper_list_field(context, self, field,
|
||||||
|
|
||||||
#
|
#
|
||||||
length = ''
|
length = ''
|
||||||
if context in ('unserialize', 'sizeof', 'unpack'):
|
if context in ('unserialize', 'unserialize_checked', 'sizeof', 'unpack', 'unpack_checked', 'sizeof_checked'):
|
||||||
int_i = ' unsigned int i;'
|
int_i = ' unsigned int i;'
|
||||||
xcb_tmp_len = ' unsigned int xcb_tmp_len;'
|
xcb_tmp_len = ' unsigned int xcb_tmp_len;'
|
||||||
if int_i not in temp_vars:
|
if int_i not in temp_vars:
|
||||||
|
@ -1037,8 +1055,18 @@ def _c_serialize_helper_list_field(context, self, field,
|
||||||
# loop over all list elements and call sizeof repeatedly
|
# loop over all list elements and call sizeof repeatedly
|
||||||
# this should be a bit faster than using the iterators
|
# this should be a bit faster than using the iterators
|
||||||
code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
|
code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
|
||||||
code_lines.append("%s xcb_tmp_len = %s(xcb_tmp%s);" %
|
if context.endswith('checked'):
|
||||||
(space, field.type.c_sizeof_name, member_arg_str))
|
code_lines.append('%s if ((const char *)xcb_end < (const char *)xcb_tmp)' % (space,))
|
||||||
|
code_lines.append('%s abort();' % (space,))
|
||||||
|
code_lines.append("%s xcb_tmp_len = %s_checked(xcb_tmp, xcb_end%s);" %
|
||||||
|
(space, field.type.c_sizeof_name, member_arg_str))
|
||||||
|
code_lines.append("%s if (xcb_tmp_len < 0)" % (space,))
|
||||||
|
code_lines.append("%s return xcb_tmp_len;" % (space,))
|
||||||
|
code_lines.append('%s if ((size_t)((const char *)xcb_end - (const char *)xcb_tmp) < xcb_tmp_len)' % (space,))
|
||||||
|
code_lines.append('%s return -1;' % (space,))
|
||||||
|
else:
|
||||||
|
code_lines.append("%s xcb_tmp_len = %s(xcb_tmp%s);" %
|
||||||
|
(space, field.type.c_sizeof_name, member_arg_str))
|
||||||
code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
|
code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
|
||||||
code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
|
code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
|
||||||
code_lines.append("%s }" % space)
|
code_lines.append("%s }" % space)
|
||||||
|
@ -1069,7 +1097,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
|
||||||
# default for simple cases: call sizeof()
|
# default for simple cases: call sizeof()
|
||||||
length = "sizeof(%s)" % field.c_field_type
|
length = "sizeof(%s)" % field.c_field_type
|
||||||
|
|
||||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
if context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked', 'sizeof', 'sizeof_checked'):
|
||||||
# default: simple cast
|
# default: simple cast
|
||||||
value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
|
value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
|
||||||
|
|
||||||
|
@ -1077,7 +1105,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
|
||||||
if field.type.is_pad and field.type.nmemb > 1:
|
if field.type.is_pad and field.type.nmemb > 1:
|
||||||
value = ''
|
value = ''
|
||||||
for i in range(field.type.nmemb):
|
for i in range(field.type.nmemb):
|
||||||
code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
|
code_lines.append('%s %s[%d] = *(const %s *)xcb_tmp;' %
|
||||||
(space, abs_field_name, i, field.c_field_type))
|
(space, abs_field_name, i, field.c_field_type))
|
||||||
# total padding = sizeof(pad0) * nmemb
|
# total padding = sizeof(pad0) * nmemb
|
||||||
length += " * %d" % field.type.nmemb
|
length += " * %d" % field.type.nmemb
|
||||||
|
@ -1128,16 +1156,16 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
|
||||||
space, prefix):
|
space, prefix):
|
||||||
prefix_str = _c_helper_fieldaccess_expr(prefix)
|
prefix_str = _c_helper_fieldaccess_expr(prefix)
|
||||||
|
|
||||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
if context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked', 'sizeof', 'sizeof_checked'):
|
||||||
value = ''
|
value = ''
|
||||||
var_field_name = 'xcb_tmp'
|
var_field_name = 'xcb_tmp'
|
||||||
|
|
||||||
# special case: intermixed fixed and variable size fields
|
# special case: intermixed fixed and variable size fields
|
||||||
if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
|
if self.c_var_followed_by_fixed_fields and context.startswith('unserialize'):
|
||||||
value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
|
value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
|
||||||
temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
|
temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
|
||||||
# special case: switch
|
# special case: switch
|
||||||
if 'unpack' == context:
|
if context.startswith('unpack'):
|
||||||
value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
|
value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
|
||||||
|
|
||||||
elif 'serialize' == context:
|
elif 'serialize' == context:
|
||||||
|
@ -1175,6 +1203,12 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
|
||||||
|
|
||||||
return (value, length)
|
return (value, length)
|
||||||
|
|
||||||
|
def _c_emit_bounds_check(code_lines, space, length):
|
||||||
|
code_lines.append('%s if ((const char *)xcb_end < (const char *)xcb_tmp)' % (space,))
|
||||||
|
code_lines.append('%s abort();' % (space,))
|
||||||
|
code_lines.append('%s if ((size_t)((const char *)xcb_end - (const char *)xcb_tmp) < %s)' % (space, length))
|
||||||
|
code_lines.append('%s return -1;' % (space,))
|
||||||
|
|
||||||
def _c_serialize_helper_fields(context, self,
|
def _c_serialize_helper_fields(context, self,
|
||||||
code_lines, temp_vars,
|
code_lines, temp_vars,
|
||||||
space, prefix, is_case_or_bitcase):
|
space, prefix, is_case_or_bitcase):
|
||||||
|
@ -1188,7 +1222,7 @@ def _c_serialize_helper_fields(context, self,
|
||||||
if not field.wire:
|
if not field.wire:
|
||||||
continue
|
continue
|
||||||
if not field.visible:
|
if not field.visible:
|
||||||
if not ((field.wire and not field.auto) or 'unserialize' == context):
|
if not ((field.wire and not field.auto) or context.startswith('unserialize')):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# switch/bitcase: fixed size fields must be considered explicitly
|
# switch/bitcase: fixed size fields must be considered explicitly
|
||||||
|
@ -1239,24 +1273,39 @@ def _c_serialize_helper_fields(context, self,
|
||||||
if field.type.fixed_size():
|
if field.type.fixed_size():
|
||||||
if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
|
if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
|
||||||
# keep track of (un)serialized object's size
|
# keep track of (un)serialized object's size
|
||||||
code_lines.append('%s xcb_block_len += %s;' % (space, length))
|
assert 'xcb_block_len' not in length
|
||||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||||
code_lines.append('%s xcb_tmp += %s;' % (space, length))
|
code_lines.append('%s xcb_tmp += %s;' % (space, length))
|
||||||
|
elif context in ('unserialize_checked', 'sizeof_checked', 'unpack_checked'):
|
||||||
|
_c_emit_bounds_check(code_lines, space, length)
|
||||||
|
code_lines.append('%s xcb_tmp += %s;' % (space, length))
|
||||||
|
code_lines.append('%s xcb_block_len += %s;' % (space, length))
|
||||||
else:
|
else:
|
||||||
# variable size objects or bitcase:
|
# variable size objects or bitcase:
|
||||||
# value & length might have been inserted earlier for special cases
|
# value & length might have been inserted earlier for special cases
|
||||||
if '' != length:
|
if '' != length:
|
||||||
# special case: intermixed fixed and variable size fields
|
# special case: intermixed fixed and variable size fields
|
||||||
if (not field.type.fixed_size() and
|
if (not field.type.fixed_size() and
|
||||||
self.c_var_followed_by_fixed_fields and 'unserialize' == context):
|
self.c_var_followed_by_fixed_fields and context.startswith('unserialize')):
|
||||||
temp_vars.append(' int %s_len;' % field.c_field_name)
|
temp_vars.append(' int %s_len;' % field.c_field_name)
|
||||||
code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
|
code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
|
||||||
|
code_lines.append('%s if (__builtin_add_overflow(xcb_block_len, %s_len, &xcb_block_len))' % (space, field.c_field_name))
|
||||||
|
if context.endswith('checked'):
|
||||||
|
code_lines.append('%s return -1;' % (space,))
|
||||||
|
_c_emit_bounds_check(code_lines, space, field.c_field_name)
|
||||||
|
else:
|
||||||
|
code_lines.append('%s abort();' % (space,))
|
||||||
code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
|
code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
|
||||||
code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
|
code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
|
||||||
else:
|
else:
|
||||||
code_lines.append('%s xcb_block_len += %s;' % (space, length))
|
code_lines.append('%s if (__builtin_add_overflow(xcb_block_len, %s, &xcb_block_len))' % (space, length))
|
||||||
|
if context.endswith('checked'):
|
||||||
|
code_lines.append('%s return -1;' % (space,))
|
||||||
|
_c_emit_bounds_check(code_lines, space, 'xcb_block_len')
|
||||||
|
else:
|
||||||
|
code_lines.append('%s abort();' % (space,))
|
||||||
# increase pointer into the byte stream accordingly
|
# increase pointer into the byte stream accordingly
|
||||||
if context in ('unserialize', 'sizeof', 'unpack'):
|
if context in ('unserialize', 'unserialize_checked', 'sizeof', 'unpack', 'unpack_checked', 'sizeof_checked'):
|
||||||
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
||||||
|
|
||||||
if 'serialize' == context:
|
if 'serialize' == context:
|
||||||
|
@ -1305,8 +1354,13 @@ def _c_serialize_helper(context, complex_type,
|
||||||
# all other data types can be evaluated one field a time
|
# all other data types can be evaluated one field a time
|
||||||
else:
|
else:
|
||||||
# unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
|
# unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
|
||||||
if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
|
if context != 'serialize' and not self.c_var_followed_by_fixed_fields:
|
||||||
code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
|
code_lines.append('%s if (__builtin_add_overflow(xcb_block_len, sizeof(%s), &xcb_block_len))' % (space, self.c_type))
|
||||||
|
if context.endswith('checked'):
|
||||||
|
code_lines.append('%s return -1;' % (space,))
|
||||||
|
_c_emit_bounds_check(code_lines, space, 'xcb_block_len')
|
||||||
|
else:
|
||||||
|
code_lines.append('%s abort();' % (space,))
|
||||||
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
|
||||||
code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
|
code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
|
||||||
code_lines.append('%s xcb_block_len = 0;' % space)
|
code_lines.append('%s xcb_block_len = 0;' % space)
|
||||||
|
@ -1321,7 +1375,7 @@ def _c_serialize_helper(context, complex_type,
|
||||||
|
|
||||||
def _c_serialize(context, self):
|
def _c_serialize(context, self):
|
||||||
"""
|
"""
|
||||||
depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
|
depending on the context variable, generate _serialize(), _unserialize(), _unpack(), _sizeof(), or _sizeof_checked()
|
||||||
for the ComplexType variable self
|
for the ComplexType variable self
|
||||||
"""
|
"""
|
||||||
_h_setlevel(1)
|
_h_setlevel(1)
|
||||||
|
@ -1331,13 +1385,16 @@ def _c_serialize(context, self):
|
||||||
# _serialize() returns the buffer size
|
# _serialize() returns the buffer size
|
||||||
_hc('int')
|
_hc('int')
|
||||||
|
|
||||||
if self.is_switch and 'unserialize' == context:
|
if self.is_switch and context.startswith('unserialize'):
|
||||||
context = 'unpack'
|
context = context.replace('serialize', 'pack')
|
||||||
|
|
||||||
cases = { 'serialize' : self.c_serialize_name,
|
cases = { 'serialize' : self.c_serialize_name,
|
||||||
'unserialize' : self.c_unserialize_name,
|
'unserialize' : self.c_unserialize_name,
|
||||||
'unpack' : self.c_unpack_name,
|
'unserialize_checked' : self.c_unserialize_name + '_checked',
|
||||||
'sizeof' : self.c_sizeof_name }
|
'unpack' : self.c_unpack_name,
|
||||||
|
'unpack_checked' : self.c_unpack_name + '_checked',
|
||||||
|
'sizeof' : self.c_sizeof_name,
|
||||||
|
'sizeof_checked' : self.c_sizeof_name + '_checked' }
|
||||||
func_name = cases[context]
|
func_name = cases[context]
|
||||||
|
|
||||||
param_fields, wire_fields, params = get_serialize_params(context, self)
|
param_fields, wire_fields, params = get_serialize_params(context, self)
|
||||||
|
@ -1391,7 +1448,7 @@ def _c_serialize(context, self):
|
||||||
prefix = [('_aux', '->', self)]
|
prefix = [('_aux', '->', self)]
|
||||||
aux_ptr = 'xcb_out'
|
aux_ptr = 'xcb_out'
|
||||||
|
|
||||||
elif context in ('unserialize', 'unpack'):
|
elif context in ('unserialize', 'unserialize_checked', 'unpack', 'unpack_checked'):
|
||||||
_c(' char *xcb_tmp = (char *)_buffer;')
|
_c(' char *xcb_tmp = (char *)_buffer;')
|
||||||
if not self.is_switch:
|
if not self.is_switch:
|
||||||
if not self.c_var_followed_by_fixed_fields:
|
if not self.c_var_followed_by_fixed_fields:
|
||||||
|
@ -1415,7 +1472,7 @@ def _c_serialize(context, self):
|
||||||
_c(' unsigned int xcb_padding_offset = %d;',
|
_c(' unsigned int xcb_padding_offset = %d;',
|
||||||
self.get_align_offset() )
|
self.get_align_offset() )
|
||||||
|
|
||||||
elif 'sizeof' == context:
|
elif context in ('sizeof', 'sizeof_checked'):
|
||||||
param_names = [p[2] for p in params]
|
param_names = [p[2] for p in params]
|
||||||
if self.length_expr is not None:
|
if self.length_expr is not None:
|
||||||
_c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
|
_c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
|
||||||
|
@ -1430,7 +1487,7 @@ def _c_serialize(context, self):
|
||||||
if self.is_switch:
|
if self.is_switch:
|
||||||
# switch: call _unpack()
|
# switch: call _unpack()
|
||||||
_c(' %s _aux;', self.c_type)
|
_c(' %s _aux;', self.c_type)
|
||||||
_c(' return %s(%s, &_aux);', self.c_unpack_name, ", ".join(param_names))
|
_c(' return %s%s(%s, &_aux);', self.c_unpack_name, context[6:], ", ".join(param_names))
|
||||||
_c('}')
|
_c('}')
|
||||||
_c_pre.redirect_end()
|
_c_pre.redirect_end()
|
||||||
return
|
return
|
||||||
|
@ -1445,6 +1502,8 @@ def _c_serialize(context, self):
|
||||||
prefix = [('_aux', '->', self)]
|
prefix = [('_aux', '->', self)]
|
||||||
if self.is_switch:
|
if self.is_switch:
|
||||||
_c(' unsigned int xcb_padding_offset = 0;')
|
_c(' unsigned int xcb_padding_offset = 0;')
|
||||||
|
else:
|
||||||
|
assert False, 'bad context %r' % context
|
||||||
|
|
||||||
count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
|
count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
|
||||||
# update variable size fields (only important for context=='serialize'
|
# update variable size fields (only important for context=='serialize'
|
||||||
|
@ -1457,7 +1516,7 @@ def _c_serialize(context, self):
|
||||||
temp_vars.append(' unsigned int xcb_block_len = 0;')
|
temp_vars.append(' unsigned int xcb_block_len = 0;')
|
||||||
temp_vars.append(' unsigned int i;')
|
temp_vars.append(' unsigned int i;')
|
||||||
temp_vars.append(' char *xcb_tmp;')
|
temp_vars.append(' char *xcb_tmp;')
|
||||||
elif 'sizeof' == context:
|
elif context.startswith('sizeof'):
|
||||||
# neither switch nor intermixed fixed and variable size fields:
|
# neither switch nor intermixed fixed and variable size fields:
|
||||||
# evaluate parameters directly
|
# evaluate parameters directly
|
||||||
if not (self.is_switch or self.c_var_followed_by_fixed_fields):
|
if not (self.is_switch or self.c_var_followed_by_fixed_fields):
|
||||||
|
@ -1486,9 +1545,9 @@ def _c_serialize(context, self):
|
||||||
# variable sized fields have been collected, now
|
# variable sized fields have been collected, now
|
||||||
# allocate memory and copy everything into a continuous memory area
|
# allocate memory and copy everything into a continuous memory area
|
||||||
# note: this is not necessary in case of unpack
|
# note: this is not necessary in case of unpack
|
||||||
if context in ('serialize', 'unserialize'):
|
if context in ('serialize', 'unserialize', 'unserialize_checked'):
|
||||||
# unserialize: check for sizeof-only invocation
|
# unserialize: check for sizeof-only invocation
|
||||||
if 'unserialize' == context:
|
if context.startswith('unserialize'):
|
||||||
_c('')
|
_c('')
|
||||||
_c(' if (NULL == _aux)')
|
_c(' if (NULL == _aux)')
|
||||||
_c(' return xcb_buffer_len;')
|
_c(' return xcb_buffer_len;')
|
||||||
|
@ -1525,8 +1584,8 @@ def _c_serialize(context, self):
|
||||||
_c(' }')
|
_c(' }')
|
||||||
|
|
||||||
# unserialize: assign variable size fields individually
|
# unserialize: assign variable size fields individually
|
||||||
if 'unserialize' == context:
|
if context.startswith('unserialize'):
|
||||||
_c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
|
_c(' xcb_tmp = ((const char *)*_aux)+xcb_buffer_len;')
|
||||||
param_fields.reverse()
|
param_fields.reverse()
|
||||||
for field in param_fields:
|
for field in param_fields:
|
||||||
if not field.type.fixed_size():
|
if not field.type.fixed_size():
|
||||||
|
@ -1683,11 +1742,11 @@ def _c_accessor_get_expr(expr, field_mapping):
|
||||||
'''
|
'''
|
||||||
lenexp = _c_accessor_get_length(expr, field_mapping)
|
lenexp = _c_accessor_get_length(expr, field_mapping)
|
||||||
|
|
||||||
if expr.op == '~':
|
if expr.op == '~': # SAFE
|
||||||
return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
|
return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
|
||||||
elif expr.op == 'popcount':
|
elif expr.op == 'popcount': # SAFE
|
||||||
return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
|
return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
|
||||||
elif expr.op == 'enumref':
|
elif expr.op == 'enumref': # SAFE
|
||||||
enum_name = expr.lenfield_type.name
|
enum_name = expr.lenfield_type.name
|
||||||
constant_name = expr.lenfield_name
|
constant_name = expr.lenfield_name
|
||||||
c_name = _n(enum_name + (constant_name,)).upper()
|
c_name = _n(enum_name + (constant_name,)).upper()
|
||||||
|
@ -2367,7 +2426,7 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
|
||||||
_c(' void *xcb_aux%d = 0;' % (idx))
|
_c(' void *xcb_aux%d = 0;' % (idx))
|
||||||
if list_with_var_size_elems:
|
if list_with_var_size_elems:
|
||||||
_c(' unsigned int xcb_tmp_len;')
|
_c(' unsigned int xcb_tmp_len;')
|
||||||
_c(' char *xcb_tmp;')
|
_c(' const char *xcb_tmp;')
|
||||||
|
|
||||||
num_fds_fixed = 0
|
num_fds_fixed = 0
|
||||||
num_fds_expr = []
|
num_fds_expr = []
|
||||||
|
|
Loading…
Reference in New Issue