summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Gosting <yukarionsen@gmail.com>2008-11-10 23:29:05 -0500
committerColin Walters <walters@verbum.org>2009-01-06 18:26:04 -0500
commitd437d9202efd8190ec6405d04627b34cb47bcc86 (patch)
tree452fd269032fac7c2d7e60e6ded9590dfa707a9f
parent1f3bcd241e5a54fa4ad8b515893783323eff6feb (diff)
Bug 18064 - more efficient validation for fixed-size type arrays
* dbus/dbus-marshal-validate.c: If an array is fixed size, skip validation Signed-off-by: Colin Walters <walters@verbum.org>
-rw-r--r--dbus/dbus-marshal-validate.c71
1 files changed, 60 insertions, 11 deletions
diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c
index b24b5bc2..35998cbb 100644
--- a/dbus/dbus-marshal-validate.c
+++ b/dbus/dbus-marshal-validate.c
@@ -370,12 +370,30 @@ validate_body_helper (DBusTypeReader *reader,
/* p may now be == end */
_dbus_assert (p <= end);
-
+
if (current_type == DBUS_TYPE_ARRAY)
{
int array_elem_type = _dbus_type_reader_get_element_type (reader);
+
+ if (!_dbus_type_is_valid (array_elem_type))
+ {
+ return DBUS_INVALID_UNKNOWN_TYPECODE;
+ }
+
alignment = _dbus_type_get_alignment (array_elem_type);
- p = _DBUS_ALIGN_ADDRESS (p, alignment);
+
+ a = _DBUS_ALIGN_ADDRESS (p, alignment);
+
+ /* a may now be == end */
+ if (a > end)
+ return DBUS_INVALID_NOT_ENOUGH_DATA;
+
+ while (p != a)
+ {
+ if (*p != '\0')
+ return DBUS_INVALID_ALIGNMENT_PADDING_NOT_NUL;
+ ++p;
+ }
}
if (claimed_len > (unsigned long) (end - p))
@@ -406,6 +424,7 @@ validate_body_helper (DBusTypeReader *reader,
DBusTypeReader sub;
DBusValidity validity;
const unsigned char *array_end;
+ int array_elem_type;
if (claimed_len > DBUS_MAXIMUM_ARRAY_LENGTH)
return DBUS_INVALID_ARRAY_LENGTH_EXCEEDS_MAXIMUM;
@@ -418,16 +437,46 @@ validate_body_helper (DBusTypeReader *reader,
array_end = p + claimed_len;
- while (p < array_end)
+ array_elem_type = _dbus_type_reader_get_element_type (reader);
+
+ /* avoid recursive call to validate_body_helper if this is an array
+ * of fixed-size elements
+ */
+ if (dbus_type_is_fixed (array_elem_type))
+ {
+ /* bools need to be handled differently, because they can
+ * have an invalid value
+ */
+ if (array_elem_type == DBUS_TYPE_BOOLEAN)
+ {
+ dbus_uint32_t v;
+ alignment = _dbus_type_get_alignment (array_elem_type);
+
+ while (p < array_end)
+ {
+ v = _dbus_unpack_uint32 (byte_order, p);
+
+ if (!(v == 0 || v == 1))
+ return DBUS_INVALID_BOOLEAN_NOT_ZERO_OR_ONE;
+
+ p += alignment;
+ }
+ }
+
+ else
+ {
+ p = array_end;
+ }
+ }
+
+ else
{
- /* FIXME we are calling a function per array element! very bad
- * need if (dbus_type_is_fixed(elem_type)) here to just skip
- * big blocks of ints/bytes/etc.
- */
-
- validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
- if (validity != DBUS_VALID)
- return validity;
+ while (p < array_end)
+ {
+ validity = validate_body_helper (&sub, byte_order, FALSE, p, end, &p);
+ if (validity != DBUS_VALID)
+ return validity;
+ }
}
if (p != array_end)