summaryrefslogtreecommitdiff
path: root/librabbitmq/amqp_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'librabbitmq/amqp_table.c')
-rw-r--r--librabbitmq/amqp_table.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/librabbitmq/amqp_table.c b/librabbitmq/amqp_table.c
index bb7813f..6bfab5e 100644
--- a/librabbitmq/amqp_table.c
+++ b/librabbitmq/amqp_table.c
@@ -15,9 +15,11 @@
#define INITIAL_ARRAY_SIZE 16
#define INITIAL_TABLE_SIZE 16
+#define TABLE_DEPTH_LIMIT 100
static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool,
- amqp_field_value_t *entry, size_t *offset);
+ amqp_field_value_t *entry, size_t *offset,
+ int depth);
static int amqp_encode_field_value(amqp_bytes_t encoded,
amqp_field_value_t *entry, size_t *offset);
@@ -25,7 +27,7 @@ static int amqp_encode_field_value(amqp_bytes_t encoded,
/*---------------------------------------------------------------------------*/
static int amqp_decode_array(amqp_bytes_t encoded, amqp_pool_t *pool,
- amqp_array_t *output, size_t *offset) {
+ amqp_array_t *output, size_t *offset, int depth) {
uint32_t arraysize;
int num_entries = 0;
int allocated_entries = INITIAL_ARRAY_SIZE;
@@ -61,7 +63,8 @@ static int amqp_decode_array(amqp_bytes_t encoded, amqp_pool_t *pool,
entries = newentries;
}
- res = amqp_decode_field_value(encoded, pool, &entries[num_entries], offset);
+ res = amqp_decode_field_value(encoded, pool, &entries[num_entries], offset,
+ depth);
if (res < 0) {
goto out;
}
@@ -90,8 +93,9 @@ out:
return res;
}
-int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool,
- amqp_table_t *output, size_t *offset) {
+static int amqp_decode_table_internal(amqp_bytes_t encoded, amqp_pool_t *pool,
+ amqp_table_t *output, size_t *offset,
+ int depth) {
uint32_t tablesize;
int num_entries = 0;
amqp_table_entry_t *entries;
@@ -99,6 +103,10 @@ int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool,
size_t limit;
int res;
+ if (depth > TABLE_DEPTH_LIMIT) {
+ return AMQP_STATUS_BAD_AMQP_DATA;
+ }
+
if (!amqp_decode_32(encoded, offset, &tablesize)) {
return AMQP_STATUS_BAD_AMQP_DATA;
}
@@ -141,7 +149,7 @@ int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool,
}
res = amqp_decode_field_value(encoded, pool, &entries[num_entries].value,
- offset);
+ offset, depth);
if (res < 0) {
goto out;
}
@@ -170,8 +178,14 @@ out:
return res;
}
+int amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool,
+ amqp_table_t *output, size_t *offset) {
+ return amqp_decode_table_internal(encoded, pool, output, offset, 0);
+}
+
static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool,
- amqp_field_value_t *entry, size_t *offset) {
+ amqp_field_value_t *entry, size_t *offset,
+ int depth) {
int res = AMQP_STATUS_BAD_AMQP_DATA;
if (!amqp_decode_8(encoded, offset, &entry->kind)) {
@@ -242,14 +256,16 @@ static int amqp_decode_field_value(amqp_bytes_t encoded, amqp_pool_t *pool,
}
case AMQP_FIELD_KIND_ARRAY:
- res = amqp_decode_array(encoded, pool, &(entry->value.array), offset);
+ res = amqp_decode_array(encoded, pool, &(entry->value.array), offset,
+ depth + 1);
goto out;
case AMQP_FIELD_KIND_TIMESTAMP:
TRIVIAL_FIELD_DECODER(64);
case AMQP_FIELD_KIND_TABLE:
- res = amqp_decode_table(encoded, pool, &(entry->value.table), offset);
+ res = amqp_decode_table_internal(encoded, pool, &(entry->value.table),
+ offset, depth + 1);
goto out;
case AMQP_FIELD_KIND_VOID: