Skip to content

Commit e35b9ca

Browse files
authored
Handle excess reason codes in SUBACK (#431)
1 parent b3dcd4e commit e35b9ca

3 files changed

Lines changed: 135 additions & 6 deletions

File tree

source/v5/mqtt5_to_mqtt3_adapter.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2093,12 +2093,11 @@ static void s_aws_mqtt5_to_mqtt3_adapter_subscribe_completion_helper(
20932093
(*subscribe_op->on_multi_suback)(
20942094
&adapter->base, subscribe_op->base.id, NULL, error_code, subscribe_op->on_multi_suback_user_data);
20952095
} else {
2096-
AWS_VARIABLE_LENGTH_ARRAY(
2097-
struct aws_mqtt_topic_subscription, multi_sub_subscription_buf, suback->reason_code_count);
2098-
AWS_VARIABLE_LENGTH_ARRAY(
2099-
struct aws_mqtt_topic_subscription *, multi_sub_subscription_ptr_buf, suback->reason_code_count);
2100-
struct aws_mqtt_topic_subscription *subscription_ptr =
2101-
(struct aws_mqtt_topic_subscription *)multi_sub_subscription_buf;
2096+
struct aws_mqtt_topic_subscription *multi_sub_subscription_buf = aws_mem_calloc(
2097+
adapter->allocator, suback->reason_code_count, sizeof(struct aws_mqtt_topic_subscription));
2098+
struct aws_mqtt_topic_subscription **multi_sub_subscription_ptr_buf = aws_mem_calloc(
2099+
adapter->allocator, suback->reason_code_count, sizeof(struct aws_mqtt_topic_subscription *));
2100+
struct aws_mqtt_topic_subscription *subscription_ptr = multi_sub_subscription_buf;
21022101

21032102
struct aws_array_list multi_sub_list;
21042103
aws_array_list_init_static(
@@ -2132,6 +2131,9 @@ static void s_aws_mqtt5_to_mqtt3_adapter_subscribe_completion_helper(
21322131
&multi_sub_list,
21332132
error_code,
21342133
subscribe_op->on_multi_suback_user_data);
2134+
2135+
aws_mem_release(adapter->allocator, multi_sub_subscription_buf);
2136+
aws_mem_release(adapter->allocator, multi_sub_subscription_ptr_buf);
21352137
}
21362138
}
21372139
}

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ add_test_case(mqtt5to3_adapter_resubscribe_nothing)
480480
add_test_case(mqtt5to3_adapter_resubscribe_something)
481481
add_test_case(mqtt5to3_adapter_subscribe_single_null_suback)
482482
add_test_case(mqtt5to3_adapter_subscribe_multi_null_suback)
483+
add_test_case(mqtt5to3_adapter_subscribe_multi_oversized_suback)
483484
add_test_case(mqtt5to3_adapter_operation_callbacks_after_shutdown)
484485
# Adapter Metrics Tests
485486
add_test_case(mqtt5to3_adapter_set_metrics_valid)

tests/v5/mqtt5_to_mqtt3_adapter_tests.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3051,6 +3051,132 @@ static int s_mqtt5to3_adapter_subscribe_multi_null_suback_fn(struct aws_allocato
30513051

30523052
AWS_TEST_CASE(mqtt5to3_adapter_subscribe_multi_null_suback, s_mqtt5to3_adapter_subscribe_multi_null_suback_fn)
30533053

3054+
#define AWS_MQTT5TO3_OVERSIZED_SUBACK_REASON_CODE_COUNT 200000
3055+
3056+
static int s_mqtt5_mock_server_send_packet_streaming(
3057+
struct aws_mqtt5_server_mock_connection_context *connection,
3058+
enum aws_mqtt5_packet_type packet_type,
3059+
void *packet) {
3060+
3061+
if (aws_mqtt5_encoder_append_packet_encoding(&connection->encoder, packet_type, packet)) {
3062+
return AWS_OP_ERR;
3063+
}
3064+
3065+
enum aws_mqtt5_encoding_result result = AWS_MQTT5_ER_OUT_OF_ROOM;
3066+
while (result == AWS_MQTT5_ER_OUT_OF_ROOM) {
3067+
struct aws_io_message *message =
3068+
aws_channel_acquire_message_from_pool(connection->slot->channel, AWS_IO_MESSAGE_APPLICATION_DATA, 4096);
3069+
if (message == NULL) {
3070+
return AWS_OP_ERR;
3071+
}
3072+
3073+
result = aws_mqtt5_encoder_encode_to_buffer(&connection->encoder, &message->message_data);
3074+
if (result == AWS_MQTT5_ER_ERROR) {
3075+
aws_mem_release(message->allocator, message);
3076+
return AWS_OP_ERR;
3077+
}
3078+
3079+
if (aws_channel_slot_send_message(connection->slot, message, AWS_CHANNEL_DIR_WRITE)) {
3080+
aws_mem_release(message->allocator, message);
3081+
return AWS_OP_ERR;
3082+
}
3083+
}
3084+
3085+
return AWS_OP_SUCCESS;
3086+
}
3087+
3088+
static int s_mqtt5_mock_server_handle_subscribe_suback_oversized(
3089+
void *packet,
3090+
struct aws_mqtt5_server_mock_connection_context *connection,
3091+
void *user_data) {
3092+
3093+
(void)user_data;
3094+
3095+
struct aws_mqtt5_packet_subscribe_view *subscribe_view = packet;
3096+
3097+
size_t reason_code_count = AWS_MQTT5TO3_OVERSIZED_SUBACK_REASON_CODE_COUNT;
3098+
3099+
enum aws_mqtt5_suback_reason_code *mqtt5_suback_codes =
3100+
aws_mem_calloc(connection->allocator, reason_code_count, sizeof(enum aws_mqtt5_suback_reason_code));
3101+
for (size_t i = 0; i < reason_code_count; ++i) {
3102+
mqtt5_suback_codes[i] = AWS_MQTT5_SARC_GRANTED_QOS_1;
3103+
}
3104+
3105+
struct aws_mqtt5_packet_suback_view suback_view = {
3106+
.packet_id = subscribe_view->packet_id,
3107+
.reason_code_count = reason_code_count,
3108+
.reason_codes = mqtt5_suback_codes,
3109+
};
3110+
3111+
int result = s_mqtt5_mock_server_send_packet_streaming(connection, AWS_MQTT5_PT_SUBACK, &suback_view);
3112+
3113+
aws_mem_release(connection->allocator, mqtt5_suback_codes);
3114+
3115+
return result;
3116+
}
3117+
3118+
static int s_mqtt5to3_adapter_subscribe_multi_oversized_suback_fn(struct aws_allocator *allocator, void *ctx) {
3119+
(void)ctx;
3120+
3121+
aws_mqtt_library_init(allocator);
3122+
3123+
struct mqtt5_client_test_options test_options;
3124+
aws_mqtt5_client_test_init_default_options(&test_options);
3125+
3126+
test_options.server_function_table.packet_handlers[AWS_MQTT5_PT_SUBSCRIBE] =
3127+
s_mqtt5_mock_server_handle_subscribe_suback_oversized;
3128+
3129+
struct aws_mqtt5_client_mqtt5_mock_test_fixture_options test_fixture_options = {
3130+
.client_options = &test_options.client_options,
3131+
.server_function_table = &test_options.server_function_table,
3132+
};
3133+
3134+
struct aws_mqtt5_to_mqtt3_adapter_test_fixture fixture;
3135+
ASSERT_SUCCESS(aws_mqtt5_to_mqtt3_adapter_test_fixture_init(&fixture, allocator, &test_fixture_options));
3136+
3137+
struct aws_mqtt_client_connection *connection = fixture.connection;
3138+
3139+
struct aws_mqtt_connection_options connection_options;
3140+
s_init_adapter_connection_options_from_fixture(&connection_options, &fixture);
3141+
3142+
connection_options.on_connection_complete = s_aws_mqtt5_to_mqtt3_adapter_test_fixture_record_connection_complete;
3143+
connection_options.user_data = &fixture;
3144+
3145+
aws_mqtt_client_connection_connect(connection, &connection_options);
3146+
3147+
s_wait_for_n_adapter_lifecycle_events(&fixture, AWS_MQTT3_LET_CONNECTION_COMPLETE, 1);
3148+
3149+
struct aws_mqtt_topic_subscription subscriptions[] = {
3150+
{
3151+
.topic = aws_byte_cursor_from_c_str("topic/1"),
3152+
.qos = AWS_MQTT_QOS_AT_LEAST_ONCE,
3153+
},
3154+
{
3155+
.topic = aws_byte_cursor_from_c_str("topic/2"),
3156+
.qos = AWS_MQTT_QOS_AT_MOST_ONCE,
3157+
},
3158+
};
3159+
3160+
struct aws_array_list subscription_list;
3161+
aws_array_list_init_static_from_initialized(
3162+
&subscription_list, subscriptions, 2, sizeof(struct aws_mqtt_topic_subscription));
3163+
3164+
aws_mqtt_client_connection_subscribe_multiple(
3165+
connection,
3166+
&subscription_list,
3167+
s_aws_mqtt5_to_mqtt3_adapter_test_fixture_record_subscribe_multi_complete,
3168+
&fixture);
3169+
3170+
s_wait_for_n_adapter_operation_events(&fixture, AWS_MQTT3_OET_SUBSCRIBE_COMPLETE, 1);
3171+
3172+
aws_mqtt5_to_mqtt3_adapter_test_fixture_clean_up(&fixture);
3173+
aws_mqtt_library_clean_up();
3174+
3175+
return AWS_OP_SUCCESS;
3176+
}
3177+
3178+
AWS_TEST_CASE(mqtt5to3_adapter_subscribe_multi_oversized_suback, s_mqtt5to3_adapter_subscribe_multi_oversized_suback_fn)
3179+
30543180
static int s_mqtt5_mock_server_handle_subscribe_suback_failure(
30553181
void *packet,
30563182
struct aws_mqtt5_server_mock_connection_context *connection,

0 commit comments

Comments
 (0)