summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-marshal-validate.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-marshal-validate.c')
-rw-r--r--dbus/dbus-marshal-validate.c184
1 files changed, 151 insertions, 33 deletions
diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c
index dbe2fa54..92050a59 100644
--- a/dbus/dbus-marshal-validate.c
+++ b/dbus/dbus-marshal-validate.c
@@ -61,6 +61,19 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
int struct_depth;
int array_depth;
int dict_entry_depth;
+ DBusValidity result;
+
+ int element_count;
+ DBusList *element_count_stack;
+
+ result = DBUS_VALID;
+ element_count_stack = NULL;
+
+ if (!_dbus_list_append (&element_count_stack, _DBUS_INT_TO_POINTER (0)))
+ {
+ result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+ goto out;
+ }
_dbus_assert (type_str != NULL);
_dbus_assert (type_pos < _DBUS_INT32_MAX - len);
@@ -68,9 +81,13 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
_dbus_assert (type_pos >= 0);
if (len > DBUS_MAXIMUM_SIGNATURE_LENGTH)
- return DBUS_INVALID_SIGNATURE_TOO_LONG;
+ {
+ result = DBUS_INVALID_SIGNATURE_TOO_LONG;
+ goto out;
+ }
p = _dbus_string_get_const_data_len (type_str, type_pos, 0);
+
end = _dbus_string_get_const_data_len (type_str, type_pos + len, 0);
struct_depth = 0;
array_depth = 0;
@@ -99,85 +116,179 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
case DBUS_TYPE_ARRAY:
array_depth += 1;
if (array_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
- return DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
+ {
+ result = DBUS_INVALID_EXCEEDED_MAXIMUM_ARRAY_RECURSION;
+ goto out;
+ }
break;
case DBUS_STRUCT_BEGIN_CHAR:
struct_depth += 1;
if (struct_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
- return DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
+ {
+ result = DBUS_INVALID_EXCEEDED_MAXIMUM_STRUCT_RECURSION;
+ goto out;
+ }
+
+ if (!_dbus_list_append (&element_count_stack,
+ _DBUS_INT_TO_POINTER (0)))
+ {
+ result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+ goto out;
+ }
+
break;
case DBUS_STRUCT_END_CHAR:
if (struct_depth == 0)
- return DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
+ {
+ result = DBUS_INVALID_STRUCT_ENDED_BUT_NOT_STARTED;
+ goto out;
+ }
if (last == DBUS_STRUCT_BEGIN_CHAR)
- return DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
+ {
+ result = DBUS_INVALID_STRUCT_HAS_NO_FIELDS;
+ goto out;
+ }
+
+ _dbus_list_pop_last (&element_count_stack);
struct_depth -= 1;
break;
case DBUS_DICT_ENTRY_BEGIN_CHAR:
if (last != DBUS_TYPE_ARRAY)
- return DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
-
+ {
+ result = DBUS_INVALID_DICT_ENTRY_NOT_INSIDE_ARRAY;
+ goto out;
+ }
+
dict_entry_depth += 1;
if (dict_entry_depth > DBUS_MAXIMUM_TYPE_RECURSION_DEPTH)
- return DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
+ {
+ result = DBUS_INVALID_EXCEEDED_MAXIMUM_DICT_ENTRY_RECURSION;
+ goto out;
+ }
+
+ if (!_dbus_list_append (&element_count_stack,
+ _DBUS_INT_TO_POINTER (0)))
+ {
+ result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+ goto out;
+ }
+
break;
case DBUS_DICT_ENTRY_END_CHAR:
if (dict_entry_depth == 0)
- return DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
-
- if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
- return DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
-
+ {
+ result = DBUS_INVALID_DICT_ENTRY_ENDED_BUT_NOT_STARTED;
+ goto out;
+ }
+
dict_entry_depth -= 1;
+
+ element_count =
+ _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
+
+ if (element_count != 2)
+ {
+ if (element_count == 0)
+ result = DBUS_INVALID_DICT_ENTRY_HAS_NO_FIELDS;
+ else if (element_count == 1)
+ result = DBUS_INVALID_DICT_ENTRY_HAS_ONLY_ONE_FIELD;
+ else
+ result = DBUS_INVALID_DICT_ENTRY_HAS_TOO_MANY_FIELDS;
+
+ goto out;
+ }
break;
case DBUS_TYPE_STRUCT: /* doesn't appear in signatures */
case DBUS_TYPE_DICT_ENTRY: /* ditto */
default:
- return DBUS_INVALID_UNKNOWN_TYPECODE;
+ result = DBUS_INVALID_UNKNOWN_TYPECODE;
+ goto out;
}
+ if (*p != DBUS_TYPE_ARRAY &&
+ *p != DBUS_DICT_ENTRY_BEGIN_CHAR &&
+ *p != DBUS_STRUCT_BEGIN_CHAR)
+ {
+ element_count =
+ _DBUS_POINTER_TO_INT (_dbus_list_pop_last (&element_count_stack));
+
+ ++element_count;
+
+ if (!_dbus_list_append (&element_count_stack,
+ _DBUS_INT_TO_POINTER (element_count)))
+ {
+ result = DBUS_VALIDITY_UNKNOWN_OOM_ERROR;
+ goto out;
+ }
+ }
+
if (array_depth > 0)
{
- if (*p == DBUS_TYPE_ARRAY)
- ;
- else if (*p == DBUS_STRUCT_END_CHAR ||
- *p == DBUS_DICT_ENTRY_END_CHAR)
- return DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+ if (*p == DBUS_TYPE_ARRAY && p != end)
+ {
+ const char *p1;
+ p1 = p + 1;
+ if (*p1 == DBUS_STRUCT_END_CHAR ||
+ *p1 == DBUS_DICT_ENTRY_END_CHAR)
+ {
+ result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+ goto out;
+ }
+ }
else
- array_depth = 0;
+ {
+ array_depth = 0;
+ }
}
if (last == DBUS_DICT_ENTRY_BEGIN_CHAR &&
!dbus_type_is_basic (*p))
- return DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
-
+ {
+ result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
+ goto out;
+ }
+
last = *p;
++p;
}
- if (array_depth > 0)
- return DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+ if (array_depth > 0)
+ {
+ result = DBUS_INVALID_MISSING_ARRAY_ELEMENT_TYPE;
+ goto out;
+ }
+
if (struct_depth > 0)
- return DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
-
+ {
+ result = DBUS_INVALID_STRUCT_STARTED_BUT_NOT_ENDED;
+ goto out;
+ }
+
if (dict_entry_depth > 0)
- return DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
-
+ {
+ result = DBUS_INVALID_DICT_ENTRY_STARTED_BUT_NOT_ENDED;
+ goto out;
+ }
+
_dbus_assert (last != DBUS_TYPE_ARRAY);
_dbus_assert (last != DBUS_STRUCT_BEGIN_CHAR);
_dbus_assert (last != DBUS_DICT_ENTRY_BEGIN_CHAR);
-
- return DBUS_VALID;
+
+ result = DBUS_VALID;
+
+out:
+ _dbus_list_clear (&element_count_stack);
+ return result;
}
static DBusValidity
@@ -387,6 +498,7 @@ validate_body_helper (DBusTypeReader *reader,
DBusValidity validity;
int contained_alignment;
int contained_type;
+ DBusValidity reason;
claimed_len = *p;
++p;
@@ -396,9 +508,15 @@ validate_body_helper (DBusTypeReader *reader,
return DBUS_INVALID_VARIANT_SIGNATURE_LENGTH_OUT_OF_BOUNDS;
_dbus_string_init_const_len (&sig, p, claimed_len);
- if (!_dbus_validate_signature (&sig, 0,
- _dbus_string_get_length (&sig)))
- return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
+ reason = _dbus_validate_signature_with_reason (&sig, 0,
+ _dbus_string_get_length (&sig));
+ if (!(reason == DBUS_VALID))
+ {
+ if (reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
+ return reason;
+ else
+ return DBUS_INVALID_VARIANT_SIGNATURE_BAD;
+ }
p += claimed_len;