summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-10-06 15:15:34 +0200
committerAleksander Morgado <aleksander@aleksander.es>2014-10-08 10:50:39 +0200
commitb439d6d13ec8a8e4ff247b7d042424f10574aa84 (patch)
tree656fc7e95ef91a13e620610e6b201a40921a0dba
parentc744b04814098ea3647de8d618bd88e5554e1a26 (diff)
downloadlibqmi-b439d6d13ec8a8e4ff247b7d042424f10574aa84.tar.gz
qmi-codegen: avoid buffer overlow in emit_input_tlv_add()
https://bugzilla.redhat.com/show_bug.cgi?id=1031738 Reported-by: Florian Weimer <fweimer@redhat.com> Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r--build-aux/qmi-codegen/Field.py12
-rw-r--r--build-aux/qmi-codegen/Variable.py2
-rw-r--r--build-aux/qmi-codegen/VariableArray.py8
-rw-r--r--build-aux/qmi-codegen/VariableInteger.py46
-rw-r--r--build-aux/qmi-codegen/VariableSequence.py4
-rw-r--r--build-aux/qmi-codegen/VariableString.py29
-rw-r--r--build-aux/qmi-codegen/VariableStruct.py4
7 files changed, 77 insertions, 28 deletions
diff --git a/build-aux/qmi-codegen/Field.py b/build-aux/qmi-codegen/Field.py
index ddbcfe1c..85426909 100644
--- a/build-aux/qmi-codegen/Field.py
+++ b/build-aux/qmi-codegen/Field.py
@@ -216,9 +216,11 @@ class Field:
Emit the code responsible for adding the TLV to the QMI message
"""
def emit_input_tlv_add(self, f, line_prefix):
+ error_label = 'ERR_EMIT_BUFFER_OVERFLOW_' + self.id_enum_name
translations = { 'name' : self.name,
'tlv_id' : self.id_enum_name,
'variable_name' : self.variable_name,
+ 'error_label' : error_label,
'lp' : line_prefix }
template = (
@@ -229,15 +231,23 @@ class Field:
f.write(string.Template(template).substitute(translations))
# Now, write the contents of the variable into the buffer
- self.variable.emit_buffer_write(f, line_prefix, 'input->' + self.variable_name, 'buffer_aux', 'buffer_len')
+ self.variable.emit_buffer_write(f, line_prefix, 'input->' + self.variable_name, 'buffer_aux', 'buffer_len', error_label)
template = (
'\n'
+ '${lp}if (FALSE) {\n'
+ '${lp} ${error_label}:\n'
+ '${lp} g_set_error (error, QMI_CORE_ERROR, QMI_CORE_ERROR_TLV_TOO_LONG, "result larger then 1024 bytes");\n'
+ '${lp} goto OUT_${error_label};\n'
+ '${lp}}\n'
+ '\n'
+ '${lp}g_assert (buffer_len <= 1024);\n'
'${lp}if (!qmi_message_add_raw_tlv (self,\n'
'${lp} (guint8)${tlv_id},\n'
'${lp} buffer,\n'
'${lp} (1024 - buffer_len),\n'
'${lp} error)) {\n'
+ '${lp} OUT_${error_label}:\n'
'${lp} g_prefix_error (error, \"Couldn\'t set the ${name} TLV: \");\n'
'${lp} qmi_message_unref (self);\n'
'${lp} return NULL;\n'
diff --git a/build-aux/qmi-codegen/Variable.py b/build-aux/qmi-codegen/Variable.py
index c238471c..fbc93f50 100644
--- a/build-aux/qmi-codegen/Variable.py
+++ b/build-aux/qmi-codegen/Variable.py
@@ -81,7 +81,7 @@ class Variable:
Emits the code involved in writing the variable to the raw byte stream
from the specific private format.
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
pass
diff --git a/build-aux/qmi-codegen/VariableArray.py b/build-aux/qmi-codegen/VariableArray.py
index 7f382023..6af3c2dc 100644
--- a/build-aux/qmi-codegen/VariableArray.py
+++ b/build-aux/qmi-codegen/VariableArray.py
@@ -296,7 +296,7 @@ class VariableArray(Variable):
Writing an array to the raw byte buffer is just about providing a loop to
write every array element one by one.
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
common_var_prefix = utils.build_underscore_name(self.name)
translations = { 'lp' : line_prefix,
'variable_name' : variable_name,
@@ -319,10 +319,10 @@ class VariableArray(Variable):
'${lp} ${common_var_prefix}_n_items = (${array_size_element_format}) ${variable_name}->len;\n')
f.write(string.Template(template).substitute(translations))
- self.array_size_element.emit_buffer_write(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len)
+ self.array_size_element.emit_buffer_write(f, line_prefix + ' ', common_var_prefix + '_n_items', buffer_name, buffer_len, error_label)
if self.array_sequence_element != '':
- self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', variable_name + '_sequence', buffer_name, buffer_len)
+ self.array_sequence_element.emit_buffer_write(f, line_prefix + ' ', variable_name + '_sequence', buffer_name, buffer_len, error_label)
template = (
@@ -330,7 +330,7 @@ class VariableArray(Variable):
'${lp} for (${common_var_prefix}_i = 0; ${common_var_prefix}_i < ${variable_name}->len; ${common_var_prefix}_i++) {\n')
f.write(string.Template(template).substitute(translations))
- self.array_element.emit_buffer_write(f, line_prefix + ' ', 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)', buffer_name, buffer_len)
+ self.array_element.emit_buffer_write(f, line_prefix + ' ', 'g_array_index (' + variable_name + ', ' + self.array_element.public_format + ',' + common_var_prefix + '_i)', buffer_name, buffer_len, error_label)
template = (
'${lp} }\n'
diff --git a/build-aux/qmi-codegen/VariableInteger.py b/build-aux/qmi-codegen/VariableInteger.py
index 235b5521..37e587d8 100644
--- a/build-aux/qmi-codegen/VariableInteger.py
+++ b/build-aux/qmi-codegen/VariableInteger.py
@@ -130,22 +130,47 @@ class VariableInteger(Variable):
'${lp}${variable_name} += 8;\n')
f.write(string.Template(template).substitute(translations))
+ """
+ Return the data type size of fixed c-types
+ """
+ @staticmethod
+ def fixed_type_byte_size(fmt):
+ if fmt == 'guint8':
+ return 1
+ if fmt == 'guint16':
+ return 2
+ if fmt == 'guint32':
+ return 4
+ if fmt == 'guint64':
+ return 8
+ if fmt == 'gint8':
+ return 1
+ if fmt == 'gint16':
+ return 2
+ if fmt == 'gint32':
+ return 4
+ if fmt == 'gint64':
+ return 8
+ raise Exception("Unsupported format %s" % (fmt))
"""
Write a single integer to the raw byte buffer
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
translations = { 'lp' : line_prefix,
'private_format' : self.private_format,
'len' : self.guint_sized_size,
'variable_name' : variable_name,
'buffer_name' : buffer_name,
'buffer_len' : buffer_len,
+ 'error_label' : error_label,
'endian' : self.endian }
if self.format == 'guint-sized':
template = (
'${lp}/* Write the ${len}-byte long variable to the buffer */\n'
+ '${lp}if (${buffer_len} < ${len})\n'
+ '${lp} goto ${error_label};\n'
'${lp}qmi_utils_write_sized_guint_to_buffer (\n'
'${lp} &${buffer_name},\n'
'${lp} &${buffer_len},\n'
@@ -153,19 +178,26 @@ class VariableInteger(Variable):
'${lp} ${endian},\n'
'${lp} &(${variable_name}));\n')
elif self.private_format == self.public_format:
+ translations['byte_size'] = VariableInteger.fixed_type_byte_size(self.private_format)
template = (
'${lp}/* Write the ${private_format} variable to the buffer */\n'
- '${lp}qmi_utils_write_${private_format}_to_buffer (\n'
- '${lp} &${buffer_name},\n'
- '${lp} &${buffer_len},\n')
+ '${lp}if (${buffer_len} < ${byte_size})\n'
+ '${lp} goto ${error_label};\n'
+ '${lp}else\n'
+ '${lp} qmi_utils_write_${private_format}_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n')
if self.private_format != 'guint8' and self.private_format != 'gint8':
template += (
- '${lp} ${endian},\n')
+ '${lp} ${endian},\n')
template += (
- '${lp} &(${variable_name}));\n')
+ '${lp} &(${variable_name}));\n')
else:
+ translations['byte_size'] = VariableInteger.fixed_type_byte_size(self.private_format)
template = (
- '${lp}{\n'
+ '${lp}if (${buffer_len} < ${byte_size})\n'
+ '${lp} goto ${error_label};\n'
+ '${lp}else {\n'
'${lp} ${private_format} tmp;\n'
'\n'
'${lp} tmp = (${private_format})${variable_name};\n'
diff --git a/build-aux/qmi-codegen/VariableSequence.py b/build-aux/qmi-codegen/VariableSequence.py
index 0ea5a9d3..bacc5419 100644
--- a/build-aux/qmi-codegen/VariableSequence.py
+++ b/build-aux/qmi-codegen/VariableSequence.py
@@ -92,9 +92,9 @@ class VariableSequence(Variable):
Writing the contents of a sequence is just about writing each of the sequence
fields one by one.
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
for member in self.members:
- member['object'].emit_buffer_write(f, line_prefix, variable_name + '_' + member['name'], buffer_name, buffer_len)
+ member['object'].emit_buffer_write(f, line_prefix, variable_name + '_' + member['name'], buffer_name, buffer_len, error_label)
"""
diff --git a/build-aux/qmi-codegen/VariableString.py b/build-aux/qmi-codegen/VariableString.py
index 0ea3bd3d..9678fbd3 100644
--- a/build-aux/qmi-codegen/VariableString.py
+++ b/build-aux/qmi-codegen/VariableString.py
@@ -157,30 +157,37 @@ class VariableString(Variable):
"""
Write a string to the raw byte buffer.
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
translations = { 'lp' : line_prefix,
'variable_name' : variable_name,
'buffer_name' : buffer_name,
+ 'error_label' : error_label,
'buffer_len' : buffer_len }
if self.is_fixed_size:
translations['fixed_size'] = self.fixed_size
template = (
'${lp}/* Write the fixed-size string variable to the buffer */\n'
- '${lp}qmi_utils_write_fixed_size_string_to_buffer (\n'
- '${lp} &${buffer_name},\n'
- '${lp} &${buffer_len},\n'
- '${lp} ${fixed_size},\n'
- '${lp} ${variable_name});\n')
+ '${lp}if (${buffer_len} < ${fixed_size})\n'
+ '${lp} goto ${error_label};\n'
+ '${lp}else\n'
+ '${lp} qmi_utils_write_fixed_size_string_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} ${fixed_size},\n'
+ '${lp} ${variable_name});\n')
else:
translations['length_prefix_size'] = self.length_prefix_size
template = (
'${lp}/* Write the string variable to the buffer */\n'
- '${lp}qmi_utils_write_string_to_buffer (\n'
- '${lp} &${buffer_name},\n'
- '${lp} &${buffer_len},\n'
- '${lp} ${length_prefix_size},\n'
- '${lp} ${variable_name});\n')
+ '${lp}if (!${variable_name} || ${buffer_len} < ${length_prefix_size} + strlen (${variable_name}))\n'
+ '${lp} goto ${error_label};\n'
+ '${lp}else\n'
+ '${lp} qmi_utils_write_string_to_buffer (\n'
+ '${lp} &${buffer_name},\n'
+ '${lp} &${buffer_len},\n'
+ '${lp} ${length_prefix_size},\n'
+ '${lp} ${variable_name});\n')
f.write(string.Template(template).substitute(translations))
diff --git a/build-aux/qmi-codegen/VariableStruct.py b/build-aux/qmi-codegen/VariableStruct.py
index 522551e6..041e6ab3 100644
--- a/build-aux/qmi-codegen/VariableStruct.py
+++ b/build-aux/qmi-codegen/VariableStruct.py
@@ -121,9 +121,9 @@ class VariableStruct(Variable):
Writing the contents of a struct is just about writing each of the struct
fields one by one.
"""
- def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len):
+ def emit_buffer_write(self, f, line_prefix, variable_name, buffer_name, buffer_len, error_label):
for member in self.members:
- member['object'].emit_buffer_write(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len)
+ member['object'].emit_buffer_write(f, line_prefix, variable_name + '.' + member['name'], buffer_name, buffer_len, error_label)
"""