diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2014-10-10 14:07:56 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2014-11-09 20:15:56 +0100 |
commit | b143b7f6ba38dd4e8b6405f479c2b8ccb90afc4e (patch) | |
tree | f08fcf105df9d5a77b10d332ab47819c9a504f46 | |
parent | 6af6f9d1cdcf765586b1ccaf569c7f6ed9b3138c (diff) | |
download | external_libqmi-b143b7f6ba38dd4e8b6405f479c2b8ccb90afc4e.zip external_libqmi-b143b7f6ba38dd4e8b6405f479c2b8ccb90afc4e.tar.gz external_libqmi-b143b7f6ba38dd4e8b6405f479c2b8ccb90afc4e.tar.bz2 |
qmi-codegen: use the new TLV reader API
-rw-r--r-- | build-aux/qmi-codegen/Field.py | 123 | ||||
-rw-r--r-- | build-aux/qmi-codegen/Variable.py | 11 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableArray.py | 122 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableInteger.py | 114 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableSequence.py | 27 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableString.py | 119 | ||||
-rw-r--r-- | build-aux/qmi-codegen/VariableStruct.py | 27 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message.c | 15 | ||||
-rw-r--r-- | src/libqmi-glib/qmi-message.h | 7 | ||||
-rw-r--r-- | src/libqmi-glib/test/test-message.c | 40 |
10 files changed, 182 insertions, 423 deletions
diff --git a/build-aux/qmi-codegen/Field.py b/build-aux/qmi-codegen/Field.py index c4b395a..7d51b93 100644 --- a/build-aux/qmi-codegen/Field.py +++ b/build-aux/qmi-codegen/Field.py @@ -41,7 +41,7 @@ class Field: # The specific TLV ID self.id = dictionary['id'] # Whether the field is to be considered mandatory in the message - self.mandatory = dictionary['mandatory'] + self.mandatory = True if dictionary['mandatory'] == 'yes' else False # The type, which must always be "TLV" self.type = dictionary['type'] # The container type, which must be either "Input" or "Output" @@ -267,49 +267,53 @@ class Field: Emit the code responsible for retrieving the TLV from the QMI message """ def emit_output_tlv_get(self, f, line_prefix): + tlv_out = utils.build_underscore_name (self.fullname) + '_out' + error = 'error' if self.mandatory else 'NULL' translations = { 'name' : self.name, 'container_underscore' : utils.build_underscore_name (self.prefix), - 'underscore' : utils.build_underscore_name (self.fullname), + 'tlv_out' : tlv_out, 'tlv_id' : self.id_enum_name, 'variable_name' : self.variable_name, 'lp' : line_prefix, - 'error' : 'error' if self.mandatory == 'yes' else 'NULL'} + 'error' : error } template = ( - '${lp}const guint8 *buffer;\n' - '${lp}guint16 buffer_len;\n' + '${lp}gsize offset = 0;\n' + '${lp}gsize init_offset;\n' + '${lp}gboolean tlv_error = FALSE;\n' '\n' - '${lp}buffer = qmi_message_get_raw_tlv (message,\n' - '${lp} ${tlv_id},\n' - '${lp} &buffer_len);\n' - '${lp}if (buffer && ${underscore}_validate (buffer, buffer_len)) {\n' - '${lp} self->${variable_name}_set = TRUE;\n' - '\n') + '${lp}init_offset = qmi_message_tlv_read_init (message, ${tlv_id}, NULL, ${error});\n') + if self.mandatory: + template += ( + '\n' + '${lp}if (init_offset == 0) {\n' + '${lp} g_prefix_error (${error}, "Couldn\'t get the mandatory ${name} TLV: ");\n' + '${lp} ${container_underscore}_unref (self);\n' + '${lp} return NULL;\n' + '${lp}}\n') + + f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the variable - self.variable.emit_buffer_read(f, line_prefix + ' ', 'self->' + self.variable_name, 'buffer', 'buffer_len') + self.variable.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, 'self->' + self.variable_name) template = ( '\n' - '${lp} /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' - '${lp} if (buffer_len > 0) {\n' - '${lp} g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV", buffer_len);\n' - '${lp} }\n') - - if self.mandatory == 'yes': + '${lp}/* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' + '${lp}if ((offset = __qmi_message_tlv_read_remaining_size (message, init_offset, offset)) > 0) {\n' + '${lp} g_warning ("Left \'%" G_GSIZE_FORMAT "\' bytes unread when getting the \'${name}\' TLV", offset);\n' + '${lp}}\n' + '\n' + '${tlv_out}:\n' + '${lp}if (!tlv_error)\n' + '${lp} self->${variable_name}_set = TRUE;\n') + if self.mandatory: template += ( - '${lp}} else {\n' - '${lp} g_set_error (error,\n' - '${lp} QMI_CORE_ERROR,\n' - '${lp} QMI_CORE_ERROR_TLV_NOT_FOUND,\n' - '${lp} \"Couldn\'t get the ${name} TLV: Not found\");\n' + '${lp}else {\n' '${lp} ${container_underscore}_unref (self);\n' '${lp} return NULL;\n' '${lp}}\n') - else: - template += ( - '${lp}}\n') f.write(string.Template(template).substitute(translations)) @@ -328,73 +332,34 @@ class Field: template = ( '\n' - 'static gboolean\n' - '${underscore}_validate (\n' - ' const guint8 *buffer,\n' - ' guint16 buffer_len)\n' - '{\n' - ' guint32 expected_len = 0;\n' - '\n') - f.write(string.Template(template).substitute(translations)) - - # Now, read the size of the expected TLV. - # - # Note: the emit_size_read() implementation is allowed to return FALSE - # to indicate an error at any time. - self.variable.emit_size_read(f, ' ', 'expected_len', 'buffer', 'buffer_len') - - template = ( - '\n' - ' if (buffer_len < expected_len) {\n' - ' g_warning ("Cannot read the \'${name}\' TLV: expected \'%u\' bytes, but only got \'%u\' bytes",\n' - ' expected_len, buffer_len);\n' - ' return FALSE;\n' - ' }\n' - '\n' - ' if (buffer_len > expected_len) {\n' - ' g_debug ("Reading the \'${name}\' TLV: expected \'%u\' bytes, but got \'%u\' bytes",\n' - ' expected_len, buffer_len);\n' - ' return TRUE;\n' - ' }\n' - '\n' - ' return TRUE;\n' - '}\n' - '\n') - f.write(string.Template(template).substitute(translations)) - - template = ( - '\n' 'static gchar *\n' '${underscore}_get_printable (\n' ' QmiMessage *message,\n' ' const gchar *line_prefix)\n' '{\n' - ' const guint8 *buffer;\n' - ' guint16 buffer_len;\n' + ' gsize offset = 0;\n' + ' gsize init_offset;\n' + ' GString *printable;\n' + ' GError *error = NULL;\n' '\n' - ' buffer = qmi_message_get_raw_tlv (message,\n' - ' ${tlv_id},\n' - ' &buffer_len);\n' - ' if (buffer && ${underscore}_validate (buffer, buffer_len)) {\n' - ' GString *printable;\n' + ' if ((init_offset = qmi_message_tlv_read_init (message, ${tlv_id}, NULL, NULL)) == 0)\n' + ' return NULL;\n' '\n' - ' printable = g_string_new ("");\n') + ' printable = g_string_new ("");\n') f.write(string.Template(template).substitute(translations)) # Now, read the contents of the buffer into the printable representation - self.variable.emit_get_printable(f, ' ', 'printable', 'buffer', 'buffer_len') + self.variable.emit_get_printable(f, ' ') template = ( '\n' - ' /* The remaining size of the buffer needs to be 0 if we successfully read the TLV */\n' - ' if (buffer_len > 0) {\n' - ' g_warning ("Left \'%u\' bytes unread when getting the \'${name}\' TLV as printable", buffer_len);\n' - ' }\n' - '\n' - ' return g_string_free (printable, FALSE);\n' - ' }\n' + ' if ((offset = __qmi_message_tlv_read_remaining_size (message, init_offset, offset)) > 0)\n' + ' g_string_append_printf (printable, "Additional unexpected \'%" G_GSIZE_FORMAT "\' bytes", offset);\n' '\n' - ' return NULL;\n' + 'out:\n' + ' if (error)\n' + ' g_string_append_printf (printable, " ERROR: %s", error->message);\n' + ' return g_string_free (printable, FALSE);\n' '}\n') f.write(string.Template(template).substitute(translations)) diff --git a/build-aux/qmi-codegen/Variable.py b/build-aux/qmi-codegen/Variable.py index a364399..cc992c6 100644 --- a/build-aux/qmi-codegen/Variable.py +++ b/build-aux/qmi-codegen/Variable.py @@ -73,7 +73,7 @@ class Variable: Emits the code involved in reading the variable from the raw byte stream into the specific private format. """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): pass @@ -86,16 +86,9 @@ class Variable: """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - pass - - - """ Emits the code to get the contents of the given variable as a printable string. """ - def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): + def emit_get_printable(self, f, line_prefix): pass """ diff --git a/build-aux/qmi-codegen/VariableArray.py b/build-aux/qmi-codegen/VariableArray.py index 68284c8..b1c8110 100644 --- a/build-aux/qmi-codegen/VariableArray.py +++ b/build-aux/qmi-codegen/VariableArray.py @@ -132,16 +132,14 @@ class VariableArray(Variable): Reading an array from the raw byte buffer is just about providing a loop to read every array element one by one. """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): common_var_prefix = utils.build_underscore_name(self.name) - translations = { 'lp' : line_prefix, - 'private_format' : self.private_format, + translations = { 'lp' : line_prefix, + 'variable_name' : variable_name, + 'private_format' : self.private_format, 'public_array_element_format' : self.array_element.public_format, - 'underscore' : self.clear_func_name(), - 'variable_name' : variable_name, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len, - 'common_var_prefix' : common_var_prefix } + 'underscore' : self.clear_func_name(), + 'common_var_prefix' : common_var_prefix } template = ( '${lp}{\n' @@ -169,21 +167,20 @@ class VariableArray(Variable): '\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) - self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len) + self.array_size_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ( '\n' '${lp} /* Read sequence in the array */\n') f.write(string.Template(template).substitute(translations)) - self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_sequence', buffer_name, buffer_len) + self.array_size_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_sequence') template = ( '\n' '${lp} ${variable_name}_sequence = ${common_var_prefix}_sequence;\n') f.write(string.Template(template).substitute(translations)) - template = ( '\n' '${lp} ${variable_name} = g_array_sized_new (\n' @@ -205,7 +202,7 @@ class VariableArray(Variable): '\n') f.write(string.Template(template).substitute(translations)) - self.array_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_aux', buffer_name, buffer_len) + self.array_element.emit_buffer_read(f, line_prefix + ' ', tlv_out, error, common_var_prefix + '_aux') template = ( '${lp} g_array_insert_val (${variable_name}, ${common_var_prefix}_i, ${common_var_prefix}_aux);\n' @@ -215,84 +212,6 @@ class VariableArray(Variable): """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - common_var_prefix = utils.build_underscore_name(self.name) - translations = { 'lp' : line_prefix, - 'variable_name' : variable_name, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len, - 'common_var_prefix' : common_var_prefix } - - template = ( - '${lp}{\n' - '${lp} guint ${common_var_prefix}_i;\n' - '\n') - f.write(string.Template(template).substitute(translations)) - - if self.fixed_size: - translations['fixed_size'] = self.fixed_size - - template = ( - '${lp} guint16 ${common_var_prefix}_n_items = ${fixed_size};\n') - f.write(string.Template(template).substitute(translations)) - else: - translations['array_size_element_format'] = self.array_size_element.public_format - if self.array_size_element.public_format == 'guint8': - translations['array_size_element_size'] = '1' - elif self.array_size_element.public_format == 'guint16': - translations['array_size_element_size'] = '2' - elif self.array_size_element.public_format == 'guint32': - translations['array_size_element_size'] = '4' - else: - raise ValueError('Invalid array size element format in %s array' % (self.name)) - - template = ( - '${lp} ${array_size_element_format} ${common_var_prefix}_n_items;\n' - '${lp} const guint8 *${common_var_prefix}_aux_buffer = &${buffer_name}[${variable_name}];\n' - '${lp} guint16 ${common_var_prefix}_aux_buffer_len;\n' - '\n' - '${lp} ${common_var_prefix}_aux_buffer_len = ((${buffer_len} >= ${variable_name}) ? ${buffer_len} - ${variable_name} : 0);\n' - '${lp} if (${common_var_prefix}_aux_buffer_len < ${array_size_element_size}) {\n' - '${lp} g_warning ("Cannot read the array size: expected \'%u\' bytes, but only got \'%u\' bytes",\n' - '${lp} ${array_size_element_size}, ${common_var_prefix}_aux_buffer_len);\n' - '${lp} return FALSE;\n' - '${lp} }\n' - '\n' - '${lp} ${variable_name} += ${array_size_element_size};\n') - - if self.array_sequence_element != '': - if self.array_sequence_element.public_format == 'guint8': - translations['array_sequence_element_size'] = '1' - elif self.array_sequence_element.public_format == 'guint16': - translations['array_sequence_element_size'] = '2' - elif self.array_sequence_element.public_format == 'guint32': - translations['array_sequence_element_size'] = '4' - else: - translations['array_sequence_element_size'] = '0' - template += ( - '\n' - '${lp} ${variable_name} += ${array_sequence_element_size};\n') - - f.write(string.Template(template).substitute(translations)) - - self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_n_items', common_var_prefix + '_aux_buffer', common_var_prefix + '_aux_buffer_len') - - template = ( - '\n' - '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' - '\n') - f.write(string.Template(template).substitute(translations)) - - self.array_element.emit_size_read(f, line_prefix + ' ', variable_name, buffer_name, buffer_len) - - template = ( - '${lp} }\n' - '${lp}}\n') - f.write(string.Template(template).substitute(translations)) - - """ Writing an array to the raw byte buffer is just about providing a loop to write every array element one by one. """ @@ -340,12 +259,9 @@ class VariableArray(Variable): The array will be printed as a list of fields enclosed between curly brackets """ - def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): + def emit_get_printable(self, f, line_prefix): common_var_prefix = utils.build_underscore_name(self.name) - translations = { 'lp' : line_prefix, - 'printable' : printable, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len, + translations = { 'lp' : line_prefix, 'common_var_prefix' : common_var_prefix } template = ( @@ -374,34 +290,34 @@ class VariableArray(Variable): '\n' '${lp} /* Read number of items in the array */\n') f.write(string.Template(template).substitute(translations)) - self.array_size_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len) + self.array_size_element.emit_buffer_read(f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_n_items') if self.array_sequence_element != '': template = ( '\n' '${lp} /* Read sequence */\n') f.write(string.Template(template).substitute(translations)) - self.array_sequence_element.emit_buffer_read(f, line_prefix + ' ', common_var_prefix + '_sequence', buffer_name, buffer_len) + self.array_sequence_element.emit_buffer_read(f, line_prefix + ' ', 'out', '&error', common_var_prefix + '_sequence') template = ( '\n' - '${lp} g_string_append_printf (${printable}, "[[Seq:%u]] ", ${common_var_prefix}_sequence);\n') + '${lp} g_string_append_printf (printable, "[[Seq:%u]] ", ${common_var_prefix}_sequence);\n') f.write(string.Template(template).substitute(translations)) template = ( '\n' - '${lp} g_string_append (${printable}, "{");\n' + '${lp} g_string_append (printable, "{");\n' '\n' '${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${common_var_prefix}_n_items; ${common_var_prefix}_i++) {\n' - '${lp} g_string_append_printf (${printable}, " [%u] = \'", ${common_var_prefix}_i);\n') + '${lp} g_string_append_printf (printable, " [%u] = \'", ${common_var_prefix}_i);\n') f.write(string.Template(template).substitute(translations)) - self.array_element.emit_get_printable(f, line_prefix + ' ', printable, buffer_name, buffer_len); + self.array_element.emit_get_printable(f, line_prefix + ' '); template = ( - '${lp} g_string_append (${printable}, " \'");\n' + '${lp} g_string_append (printable, " \'");\n' '${lp} }\n' '\n' - '${lp} g_string_append (${printable}, "}");\n' + '${lp} g_string_append (printable, "}");\n' '${lp}}') f.write(string.Template(template).substitute(translations)) diff --git a/build-aux/qmi-codegen/VariableInteger.py b/build-aux/qmi-codegen/VariableInteger.py index 02d5b80..44a0761 100644 --- a/build-aux/qmi-codegen/VariableInteger.py +++ b/build-aux/qmi-codegen/VariableInteger.py @@ -56,81 +56,41 @@ class VariableInteger(Variable): """ Read a single integer from the raw byte buffer """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): translations = { 'lp' : line_prefix, + 'tlv_out' : tlv_out, + 'variable_name' : variable_name, + 'error' : error, 'public_format' : self.public_format, 'private_format' : self.private_format, - 'len' : self.guint_sized_size, - 'variable_name' : variable_name, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len, - 'endian' : self.endian } + 'len' : self.guint_sized_size } + + if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat': + translations['endian'] = ' ' + self.endian + ',' + else: + translations['endian'] = '' if self.format == 'guint-sized': template = ( - '${lp}/* Read the ${len}-byte long variable from the buffer */\n' - '${lp}qmi_utils_read_sized_guint_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${len},\n' - '${lp} ${endian},\n' - '${lp} &(${variable_name}));\n') + '${lp}if (!qmi_message_tlv_read_sized_guint (message, init_offset, &offset, ${len},${endian} &(${variable_name}), ${error}))\n' + '${lp} goto ${tlv_out};\n') elif self.private_format == self.public_format: template = ( - '${lp}/* Read the ${private_format} variable from the buffer */\n' - '${lp}qmi_utils_read_${private_format}_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n') - if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat': - template += ( - '${lp} ${endian},\n') - template += ( - '${lp} &(${variable_name}));\n') + '${lp}if (!qmi_message_tlv_read_${private_format} (message, init_offset, &offset,${endian} &(${variable_name}), ${error}))\n' + '${lp} goto ${tlv_out};\n') else: template = ( '${lp}{\n' '${lp} ${private_format} tmp;\n' '\n' - '${lp} /* Read the ${private_format} variable from the buffer */\n' - '${lp} qmi_utils_read_${private_format}_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n') - if self.private_format != 'guint8' and self.private_format != 'gint8': - template += ( - '${lp} ${endian},\n') - template += ( - '${lp} &tmp);\n' + '${lp} if (!qmi_message_tlv_read_${private_format} (message, init_offset, &offset,${endian} &tmp, ${error}))\n' + '${lp} goto ${tlv_out};\n' '${lp} ${variable_name} = (${public_format})tmp;\n' '${lp}}\n') f.write(string.Template(template).substitute(translations)) """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'len' : self.guint_sized_size, - 'variable_name' : variable_name } - template = '' - if self.format == 'guint-sized': - template += ( - '${lp}${variable_name} += ${len};\n') - elif self.private_format == 'guint8' or self.private_format == 'gint8': - template += ( - '${lp}${variable_name} += 1;\n') - elif self.private_format == 'guint16' or self.private_format == 'gint16': - template += ( - '${lp}${variable_name} += 2;\n') - elif self.private_format == 'guint32' or self.private_format == 'gint32' or self.private_format == 'gfloat': - template += ( - '${lp}${variable_name} += 4;\n') - elif self.private_format == 'guint64' or self.private_format == 'gint64': - template += ( - '${lp}${variable_name} += 8;\n') - f.write(string.Template(template).substitute(translations)) - - """ Return the data type size of fixed c-types """ @staticmethod @@ -229,12 +189,14 @@ class VariableInteger(Variable): 'private_format' : self.private_format, 'public_format' : self.public_format, 'len' : self.guint_sized_size, - 'printable' : printable, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len, 'common_format' : common_format, - 'common_cast' : common_cast, - 'endian' : self.endian } + 'common_cast' : common_cast } + + if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat': + translations['endian'] = ' ' + self.endian + ',' + else: + translations['endian'] = '' + template = ( '\n' '${lp}{\n' @@ -243,42 +205,28 @@ class VariableInteger(Variable): if self.format == 'guint-sized': template += ( - '${lp} /* Read the ${len}-byte long variable from the buffer */\n' - '${lp} qmi_utils_read_sized_guint_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${len},\n' - '${lp} ${endian},\n' - '${lp} &tmp);\n' - '\n') + '${lp} if (!qmi_message_tlv_read_sized_guint (message, init_offset, &offset, ${len},${endian} &tmp, &error))\n' + '${lp} goto out;\n') else: template += ( - '${lp} /* Read the ${private_format} variable from the buffer */\n' - '${lp} qmi_utils_read_${private_format}_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n') - if self.private_format != 'guint8' and self.private_format != 'gint8' and self.private_format != 'gfloat': - template += ( - '${lp} ${endian},\n') - template += ( - '${lp} &tmp);\n' - '\n') + '${lp} if (!qmi_message_tlv_read_${private_format} (message, init_offset, &offset,${endian} &tmp, &error))\n' + '${lp} goto out;\n') if self.public_format == 'gboolean': template += ( - '${lp} g_string_append_printf (${printable}, "%s", tmp ? "yes" : "no");\n') + '${lp} g_string_append_printf (printable, "%s", tmp ? "yes" : "no");\n') elif self.public_format != self.private_format: translations['public_type_underscore'] = utils.build_underscore_name_from_camelcase(self.public_format) translations['public_type_underscore_upper'] = utils.build_underscore_name_from_camelcase(self.public_format).upper() template += ( '#if defined __${public_type_underscore_upper}_IS_ENUM__\n' - '${lp} g_string_append_printf (${printable}, "%s", ${public_type_underscore}_get_string ((${public_format})tmp));\n' + '${lp} g_string_append_printf (printable, "%s", ${public_type_underscore}_get_string ((${public_format})tmp));\n' '#elif defined __${public_type_underscore_upper}_IS_FLAGS__\n' '${lp} {\n' '${lp} gchar *flags_str;\n' '\n' '${lp} flags_str = ${public_type_underscore}_build_string_from_mask ((${public_format})tmp);\n' - '${lp} g_string_append_printf (${printable}, "%s", flags_str);\n' + '${lp} g_string_append_printf (printable, "%s", flags_str);\n' '${lp} g_free (flags_str);\n' '${lp} }\n' '#else\n' @@ -286,7 +234,7 @@ class VariableInteger(Variable): '#endif\n') else: template += ( - '${lp} g_string_append_printf (${printable}, "${common_format}", ${common_cast}tmp);\n') + '${lp} g_string_append_printf (printable, "${common_format}", ${common_cast}tmp);\n') template += ( '${lp}}\n') diff --git a/build-aux/qmi-codegen/VariableSequence.py b/build-aux/qmi-codegen/VariableSequence.py index 03dd2d7..c69a0e6 100644 --- a/build-aux/qmi-codegen/VariableSequence.py +++ b/build-aux/qmi-codegen/VariableSequence.py @@ -75,17 +75,9 @@ class VariableSequence(Variable): Reading the contents of a sequence is just about reading each of the sequence fields one by one. """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): for member in self.members: - member['object'].emit_buffer_read(f, line_prefix, variable_name + '_' + member['name'], buffer_name, buffer_len) - - - """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - for member in self.members: - member['object'].emit_size_read(f, line_prefix, variable_name, buffer_name, buffer_len) + member['object'].emit_buffer_read(f, line_prefix, tlv_out, error, variable_name + '_' + member['name']) """ @@ -101,28 +93,27 @@ class VariableSequence(Variable): The sequence will be printed as a list of fields enclosed between square brackets """ - def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'printable' : printable } + def emit_get_printable(self, f, line_prefix): + translations = { 'lp' : line_prefix } template = ( - '${lp}g_string_append (${printable}, "[");\n') + '${lp}g_string_append (printable, "[");\n') f.write(string.Template(template).substitute(translations)) for member in self.members: translations['variable_name'] = member['name'] template = ( - '${lp}g_string_append (${printable}, " ${variable_name} = \'");\n') + '${lp}g_string_append (printable, " ${variable_name} = \'");\n') f.write(string.Template(template).substitute(translations)) - member['object'].emit_get_printable(f, line_prefix, printable, buffer_name, buffer_len) + member['object'].emit_get_printable(f, line_prefix) template = ( - '${lp}g_string_append (${printable}, "\'");\n') + '${lp}g_string_append (printable, "\'");\n') f.write(string.Template(template).substitute(translations)) template = ( - '${lp}g_string_append (${printable}, " ]");\n') + '${lp}g_string_append (printable, " ]");\n') f.write(string.Template(template).substitute(translations)) diff --git a/build-aux/qmi-codegen/VariableString.py b/build-aux/qmi-codegen/VariableString.py index 44fe50e..355fe4a 100644 --- a/build-aux/qmi-codegen/VariableString.py +++ b/build-aux/qmi-codegen/VariableString.py @@ -75,87 +75,24 @@ class VariableString(Variable): """ Read a string from the raw byte buffer. """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'variable_name' : variable_name, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len } + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): + translations = { 'lp' : line_prefix, + 'tlv_out' : tlv_out, + 'variable_name' : variable_name, + 'error' : error } if self.is_fixed_size: translations['fixed_size'] = self.fixed_size template = ( - '${lp}/* Read the fixed-size string variable from the buffer */\n' - '${lp}qmi_utils_read_fixed_size_string_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${fixed_size},\n' - '${lp} &${variable_name}[0]);\n' + '${lp}if (!qmi_message_tlv_read_fixed_size_string (message, init_offset, &offset, ${fixed_size}, &${variable_name}[0], ${error}))\n' + '${lp} goto ${tlv_out};\n' '${lp}${variable_name}[${fixed_size}] = \'\\0\';\n') else: - translations['length_prefix_size'] = self.length_prefix_size + translations['n_size_prefix_bytes'] = self.n_size_prefix_bytes translations['max_size'] = self.max_size if self.max_size != '' else '0' template = ( - '${lp}/* Read the string variable from the buffer */\n' - '${lp}qmi_utils_read_string_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${length_prefix_size},\n' - '${lp} ${max_size},\n' - '${lp} &(${variable_name}));\n') - - f.write(string.Template(template).substitute(translations)) - - - """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'variable_name' : variable_name, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len } - - if self.is_fixed_size: - translations['fixed_size'] = self.fixed_size - template = ( - '${lp}${variable_name} += ${fixed_size};\n') - elif self.length_prefix_size == 0: - template = ( - '${lp}${variable_name} += ${buffer_len};\n') - elif self.length_prefix_size == 8: - template = ( - '${lp}{\n' - '${lp} guint8 size8;\n' - '${lp} const guint8 *aux_buffer = &${buffer_name}[${variable_name}];\n' - '${lp} guint16 aux_buffer_len;\n' - '\n' - '${lp} aux_buffer_len = ((${buffer_len} >= ${variable_name}) ? ${buffer_len} - ${variable_name} : 0);\n' - '${lp} if (aux_buffer_len < 1) {\n' - '${lp} g_warning ("Cannot read the string size: expected \'1\' bytes, but only got \'%u\' bytes",\n' - '${lp} aux_buffer_len);\n' - '${lp} return FALSE;\n' - '${lp} }\n' - '\n' - '${lp} qmi_utils_read_guint8_from_buffer (&aux_buffer, &aux_buffer_len, &size8);\n' - '${lp} ${variable_name} += (1 + size8);\n' - '${lp}}\n') - elif self.length_prefix_size == 16: - template = ( - '${lp}{\n' - '${lp} guint16 size16;\n' - '${lp} const guint8 *aux_buffer = &${buffer_name}[${variable_name}];\n' - '${lp} guint16 aux_buffer_len;\n' - '\n' - '${lp} aux_buffer_len = ((${buffer_len} >= ${variable_name}) ? ${buffer_len} - ${variable_name} : 0);\n' - '${lp} if (aux_buffer_len < 2) {\n' - '${lp} g_warning ("Cannot read the string size: expected \'2\' bytes, but only got \'%u\' bytes",\n' - '${lp} aux_buffer_len);\n' - '${lp} return FALSE;\n' - '${lp} }\n' - '\n' - '${lp} qmi_utils_read_guint16_from_buffer (&aux_buffer, &aux_buffer_len, QMI_ENDIAN_LITTLE, &size16);\n' - '${lp} ${variable_name} += (2 + size16);\n' - '${lp}}\n') + '${lp}if (!qmi_message_tlv_read_string (message, init_offset, &offset, ${n_size_prefix_bytes}, ${max_size}, &(${variable_name}), ${error}))\n' + '${lp} goto ${tlv_out};\n') f.write(string.Template(template).substitute(translations)) @@ -181,47 +118,31 @@ class VariableString(Variable): """ Get the string as printable """ - def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'printable' : printable, - 'buffer_name' : buffer_name, - 'buffer_len' : buffer_len } + def emit_get_printable(self, f, line_prefix): + translations = { 'lp' : line_prefix } if self.is_fixed_size: translations['fixed_size'] = self.fixed_size - translations['fixed_size_plus_one'] = int(self.fixed_size) + 1 template = ( '\n' '${lp}{\n' - '${lp} gchar tmp[${fixed_size_plus_one}];\n' - '\n' - '${lp} /* Read the fixed-size string variable from the buffer */\n' - '${lp} qmi_utils_read_fixed_size_string_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${fixed_size},\n' - '${lp} &tmp[0]);\n' - '${lp} tmp[${fixed_size}] = \'\\0\';\n' + '${lp} gchar tmp[${fixed_size}];\n' '\n' - '${lp} g_string_append_printf (${printable}, "%s", tmp);\n' + '${lp} if (!qmi_message_tlv_read_fixed_size_string (message, init_offset, &offset, ${fixed_size}, &tmp[0], &error))\n' + '${lp} goto out;\n' + '${lp} g_string_append_len (printable, tmp, ${fixed_size});\n' '${lp}}\n') else: - translations['length_prefix_size'] = self.length_prefix_size + translations['n_size_prefix_bytes'] = self.n_size_prefix_bytes translations['max_size'] = self.max_size if self.max_size != '' else '0' template = ( '\n' '${lp}{\n' '${lp} gchar *tmp;\n' '\n' - '${lp} /* Read the string variable from the buffer */\n' - '${lp} qmi_utils_read_string_from_buffer (\n' - '${lp} &${buffer_name},\n' - '${lp} &${buffer_len},\n' - '${lp} ${length_prefix_size},\n' - '${lp} ${max_size},\n' - '${lp} &tmp);\n' - '\n' - '${lp} g_string_append_printf (${printable}, "%s", tmp);\n' + '${lp} if (!qmi_message_tlv_read_string (message, init_offset, &offset, ${n_size_prefix_bytes}, ${max_size}, &tmp, &error))\n' + '${lp} goto out;\n' + '${lp} g_string_append (printable, tmp);\n' '${lp} g_free (tmp);\n' '${lp}}\n') diff --git a/build-aux/qmi-codegen/VariableStruct.py b/build-aux/qmi-codegen/VariableStruct.py index 1e96e5d..b19b4c6 100644 --- a/build-aux/qmi-codegen/VariableStruct.py +++ b/build-aux/qmi-codegen/VariableStruct.py @@ -104,17 +104,9 @@ class VariableStruct(Variable): Reading the contents of a struct is just about reading each of the struct fields one by one. """ - def emit_buffer_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): + def emit_buffer_read(self, f, line_prefix, tlv_out, error, variable_name): for member in self.members: - member['object'].emit_buffer_read(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len) - - - """ - Emits the code involved in computing the size of the variable. - """ - def emit_size_read(self, f, line_prefix, variable_name, buffer_name, buffer_len): - for member in self.members: - member['object'].emit_size_read(f, line_prefix, variable_name, buffer_name, buffer_len) + member['object'].emit_buffer_read(f, line_prefix, tlv_out, error, variable_name + '.' + member['name']) """ @@ -130,28 +122,27 @@ class VariableStruct(Variable): The struct will be printed as a list of fields enclosed between square brackets """ - def emit_get_printable(self, f, line_prefix, printable, buffer_name, buffer_len): - translations = { 'lp' : line_prefix, - 'printable' : printable } + def emit_get_printable(self, f, line_prefix): + translations = { 'lp' : line_prefix } template = ( - '${lp}g_string_append (${printable}, "[");\n') + '${lp}g_string_append (printable, "[");\n') f.write(string.Template(template).substitute(translations)) for member in self.members: translations['variable_name'] = member['name'] template = ( - '${lp}g_string_append (${printable}, " ${variable_name} = \'");\n') + '${lp}g_string_append (printable, " ${variable_name} = \'");\n') f.write(string.Template(template).substitute(translations)) - member['object'].emit_get_printable(f, line_prefix, printable, buffer_name, buffer_len) + member['object'].emit_get_printable(f, line_prefix) template = ( - '${lp}g_string_append (${printable}, "\'");\n') + '${lp}g_string_append (printable, "\'");\n') f.write(string.Template(template).substitute(translations)) template = ( - '${lp}g_string_append (${printable}, " ]");\n') + '${lp}g_string_append (printable, " ]");\n') f.write(string.Template(template).substitute(translations)) diff --git a/src/libqmi-glib/qmi-message.c b/src/libqmi-glib/qmi-message.c index 07ed279..92d6d4b 100644 --- a/src/libqmi-glib/qmi-message.c +++ b/src/libqmi-glib/qmi-message.c @@ -1829,6 +1829,21 @@ qmi_message_tlv_read_fixed_size_string (QmiMessage *self, return TRUE; } +guint16 +__qmi_message_tlv_read_remaining_size (QmiMessage *self, + gsize tlv_offset, + gsize offset) +{ + struct tlv *tlv; + + g_return_val_if_fail (self != NULL, FALSE); + + tlv = (struct tlv *) &(self->data[tlv_offset]); + + g_warn_if_fail (tlv->length >= offset); + return (tlv->length >= offset ? (tlv->length - offset) : 0); +} + /*****************************************************************************/ /** diff --git a/src/libqmi-glib/qmi-message.h b/src/libqmi-glib/qmi-message.h index 1c7331c..9e2a1dc 100644 --- a/src/libqmi-glib/qmi-message.h +++ b/src/libqmi-glib/qmi-message.h @@ -215,6 +215,13 @@ gboolean qmi_message_tlv_read_fixed_size_string (QmiMessage *self, gchar *out, GError **error); +#if defined (LIBQMI_GLIB_COMPILATION) +G_GNUC_INTERNAL +guint16 __qmi_message_tlv_read_remaining_size (QmiMessage *self, + gsize tlv_offset, + gsize offset); +#endif + /*****************************************************************************/ /* Raw TLV handling */ diff --git a/src/libqmi-glib/test/test-message.c b/src/libqmi-glib/test/test-message.c index 94d4955..c19a6be 100644 --- a/src/libqmi-glib/test/test-message.c +++ b/src/libqmi-glib/test/test-message.c @@ -174,7 +174,30 @@ test_message_parse_complete_and_complete (void) test_message_parse_common (buffer, sizeof (buffer), 2); } -#if GLIB_CHECK_VERSION (2,34,0) +static void +test_message_overflow_common (const guint8 *buffer, + guint buffer_len) +{ + QmiMessage *message; + GByteArray *array; + GError *error = NULL; + gchar *printable; + + array = g_byte_array_sized_new (buffer_len); + g_byte_array_append (array, buffer, buffer_len); + message = qmi_message_new_from_raw (array, &error); + g_assert_no_error (error); + g_assert (message); + + printable = qmi_message_get_printable (message, ""); + g_print ("\n%s\n", printable); + g_assert (strstr (printable, "ERROR: Reading TLV would overflow")); + g_free (printable); + + g_byte_array_unref (array); + qmi_message_unref (message); +} + static void test_message_parse_wrong_tlv (void) { @@ -188,11 +211,7 @@ test_message_parse_wrong_tlv (void) 0x06, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x05 }; - g_test_expect_message ("Qmi", - G_LOG_LEVEL_WARNING, - "Cannot read the '*' TLV: expected '*' bytes, but only got '*' bytes"); - test_message_parse_common (buffer, sizeof (buffer), 1); - g_test_assert_expected_messages (); + test_message_overflow_common (buffer, G_N_ELEMENTS (buffer)); } static void @@ -215,13 +234,8 @@ test_message_parse_missing_size (void) 0x01 }; - g_test_expect_message ("Qmi", - G_LOG_LEVEL_WARNING, - "Cannot read the string size: expected '*' bytes, but only got '*' bytes"); - test_message_parse_common (buffer, sizeof (buffer), 1); - g_test_assert_expected_messages (); + test_message_overflow_common (buffer, G_N_ELEMENTS (buffer)); } -#endif /*****************************************************************************/ @@ -1498,10 +1512,8 @@ int main (int argc, char **argv) g_test_add_func ("/libqmi-glib/message/parse/complete", test_message_parse_complete); g_test_add_func ("/libqmi-glib/message/parse/complete-and-short", test_message_parse_complete_and_short); g_test_add_func ("/libqmi-glib/message/parse/complete-and-complete", test_message_parse_complete_and_complete); -#if GLIB_CHECK_VERSION (2,34,0) g_test_add_func ("/libqmi-glib/message/parse/wrong-tlv", test_message_parse_wrong_tlv); g_test_add_func ("/libqmi-glib/message/parse/missing-size", test_message_parse_missing_size); -#endif g_test_add_func ("/libqmi-glib/message/new/request", test_message_new_request); g_test_add_func ("/libqmi-glib/message/new/response/ok", test_message_new_response_ok); |