From 4f451c7382591072735767de28bc201c2d14e4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Ku=C4=87ma?= Date: Tue, 21 Nov 2023 12:40:44 +0100 Subject: [PATCH] Anjay 3.6.1 Improvements: - Optimized heap memory usage: SenML CBOR payloads for Send and Notify operations are no longer serialized in memory in their entirety unless their contents depend on the Access Control object state - Added a public define for MSISDN string size - Optimized "Out of memory" logs in favor of a smaller flash memory footprint Bugfixes: - (commercial feature only) Fixes for various bugs that could cause invalid memory accesses when restoring data from corrupted core persistence data --- CHANGELOG.md | 16 +++++ CMakeLists.txt | 2 +- .../include_public/avsystem/coap/observe.h | 23 +++++- deps/avs_coap/src/avs_coap_observe.c | 42 +++-------- deps/avs_coap/tests/udp/streaming_observe.c | 8 ++- deps/avs_commons | 2 +- .../FU-SecureDownloads.rst | 7 +- .../avsystem/commons/avs_commons_config.h | 10 +++ .../avsystem/commons/avs_commons_config.h | 10 +++ .../avsystem/commons/avs_commons_config.h | 10 +++ .../avsystem/commons/avs_commons_config.h | 10 +++ src/anjay_config_log.h | 5 ++ src/anjay_modules/anjay_utils_core.h | 2 + src/core/anjay_access_utils.c | 66 +++++++++++++---- src/core/anjay_access_utils_private.h | 37 ++++++++++ src/core/anjay_bootstrap_core.c | 2 +- src/core/anjay_core.c | 14 ++-- src/core/anjay_dm_core.c | 4 +- src/core/anjay_event_loop.c | 2 +- src/core/anjay_io_core.h | 11 ++- src/core/anjay_lwm2m_send.c | 10 ++- src/core/anjay_notify.c | 12 ++-- src/core/anjay_utils_core.c | 10 ++- src/core/attr_storage/anjay_attr_storage.c | 4 +- src/core/dm/anjay_dm_handlers.c | 2 +- src/core/dm/anjay_dm_read.c | 4 +- src/core/dm/anjay_modules.c | 2 +- src/core/downloader/anjay_coap.c | 2 +- src/core/downloader/anjay_http.c | 2 +- src/core/io/anjay_batch_builder.c | 54 +++++++++----- src/core/io/anjay_batch_builder.h | 29 ++++++++ src/core/io/anjay_dynamic.c | 54 +++++++++----- src/core/io/anjay_senml_like_encoder.h | 10 ++- src/core/io/anjay_senml_like_out.c | 12 +++- src/core/io/cbor/anjay_senml_cbor_encoder.c | 56 +++++++++++---- src/core/observe/anjay_observe_core.c | 71 +++++++++++++----- src/core/servers/anjay_activate.c | 2 +- src/core/servers/anjay_connections.c | 2 +- src/core/servers/anjay_register.c | 4 +- src/core/servers/anjay_security_generic.c | 11 +-- src/core/servers/anjay_servers_internal.c | 2 +- .../anjay_access_control_handlers.c | 8 +-- .../anjay_access_control_persistence.c | 2 +- .../access_control/anjay_mod_access_control.c | 2 +- .../anjay_advanced_fw_update.c | 16 ++--- src/modules/fw_update/anjay_fw_update.c | 6 +- src/modules/ipso/anjay_ipso_3d_sensor.c | 2 +- src/modules/ipso/anjay_ipso_basic_sensor.c | 2 +- src/modules/ipso/anjay_ipso_button.c | 2 +- src/modules/security/anjay_mod_security.c | 9 ++- src/modules/server/anjay_mod_server.c | 4 +- tests/core/io/cbor/cbor_encoder.c | 72 ++++++++++++++----- tests/core/io/dm_batch.c | 22 +++--- tests/core/io/dynamic.c | 2 +- tests/core/io/senml_cbor_encoder.c | 3 +- tests/core/observe/observe.c | 2 +- tests/fuzz/CMakeLists.txt | 2 + 57 files changed, 563 insertions(+), 231 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df8ba36a..7ab2169a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 3.6.1 (November 21st, 2023) + +### Improvements + +- Optimized heap memory usage: SenML CBOR payloads for Send and Notify + operations are no longer serialized in memory in their entirety unless their + contents depend on the Access Control object state +- Added a public define for MSISDN string size +- Optimized "Out of memory" logs in favor of a smaller flash memory footprint + +### Bugfixes + +- (commercial feature only) Fixes for various bugs that could cause invalid + memory accesses when restoring data from corrupted core persistence data + ## 3.6.0 (October 9th, 2023) ### Features @@ -9,6 +24,7 @@ - Added `requirements.txt` file to manage Python dependencies more efficiently ### Improvements + - Clarified documentation on behavior of Firmware Update and Advanced Firmware Update modules when ``anjay_fw_update_get_security_config_t`` and ``anjay_advanced_fw_update_perform_upgrade_t`` callbacks, respectively, are diff --git a/CMakeLists.txt b/CMakeLists.txt index 038bbd93..018a44d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.6.0) project(anjay C) -set(ANJAY_VERSION "3.6.0" CACHE STRING "Anjay library version") +set(ANJAY_VERSION "3.6.1" CACHE STRING "Anjay library version") set(ANJAY_BINARY_VERSION 1.0.0) set(ANJAY_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/deps/avs_coap/include_public/avsystem/coap/observe.h b/deps/avs_coap/include_public/avsystem/coap/observe.h index 6551bf48..488d7b58 100644 --- a/deps/avs_coap/include_public/avsystem/coap/observe.h +++ b/deps/avs_coap/include_public/avsystem/coap/observe.h @@ -125,6 +125,9 @@ avs_error_t avs_coap_observe_persist(avs_coap_ctx_t *ctx, * * @param handler_arg Opaque argument to pass to @p cancel_handler. * + * @param out_id Pointer to a variable that (if not NULL) will be filled + * with the ID of the restored observation. + * * @param persistence Persistence context to operate on. * * @returns @@ -134,12 +137,26 @@ avs_error_t avs_coap_observe_persist(avs_coap_ctx_t *ctx, * - avs_errno(AVS_EINVAL) if the CoAP context is already initialized * - any I/O error forwarded from the underlying stream */ -avs_error_t +avs_error_t avs_coap_observe_restore_with_id( + avs_coap_ctx_t *ctx, + avs_coap_observe_cancel_handler_t *cancel_handler, + void *handler_arg, + avs_coap_observe_id_t *out_id, + avs_persistence_context_t *persistence); + +/** + * Restores single Observe entry from the specified @p persistence context. This + * is a version of @ref avs_coap_observe_restore_with_id without the + * out_id argument declared to maitain backwards compatibility. + */ +static inline avs_error_t avs_coap_observe_restore(avs_coap_ctx_t *ctx, avs_coap_observe_cancel_handler_t *cancel_handler, void *handler_arg, - avs_persistence_context_t *persistence); - + avs_persistence_context_t *persistence) { + return avs_coap_observe_restore_with_id( + ctx, cancel_handler, handler_arg, NULL, persistence); +} #endif // WITH_AVS_COAP_OBSERVE_PERSISTENCE #ifdef WITH_AVS_COAP_OBSERVE diff --git a/deps/avs_coap/src/avs_coap_observe.c b/deps/avs_coap/src/avs_coap_observe.c index a042ead0..c9b0f462 100644 --- a/deps/avs_coap/src/avs_coap_observe.c +++ b/deps/avs_coap/src/avs_coap_observe.c @@ -213,11 +213,12 @@ avs_error_t avs_coap_observe_persist(avs_coap_ctx_t *ctx, return err; } -avs_error_t -avs_coap_observe_restore(avs_coap_ctx_t *ctx, - avs_coap_observe_cancel_handler_t *cancel_handler, - void *handler_arg, - avs_persistence_context_t *persistence) { +avs_error_t avs_coap_observe_restore_with_id( + avs_coap_ctx_t *ctx, + avs_coap_observe_cancel_handler_t *cancel_handler, + void *handler_arg, + avs_coap_observe_id_t *out_id, + avs_persistence_context_t *persistence) { if (avs_persistence_direction(persistence) != AVS_PERSISTENCE_RESTORE) { return avs_errno(AVS_EINVAL); } @@ -272,37 +273,12 @@ avs_coap_observe_restore(avs_coap_ctx_t *ctx, LOG(DEBUG, _("Observe (restored) start: ") "%s", AVS_COAP_TOKEN_HEX(&id.token)); AVS_LIST_INSERT(&coap_base->observes, observe); - + if (out_id) { + *out_id = id; + } return AVS_OK; } -# else // WITH_AVS_COAP_OBSERVE_PERSISTENCE - -avs_error_t avs_coap_observe_persist(avs_coap_ctx_t *ctx, - avs_coap_observe_id_t id, - avs_persistence_context_t *persistence) { - (void) ctx; - (void) id; - (void) persistence; - - LOG(WARNING, _("observe persistence not compiled in")); - return _avs_coap_err(AVS_COAP_ERR_FEATURE_DISABLED); -} - -avs_error_t -avs_coap_observe_restore(avs_coap_ctx_t *ctx, - avs_coap_observe_cancel_handler_t *cancel_handler, - void *handler_arg, - avs_persistence_context_t *persistence) { - (void) ctx; - (void) cancel_handler; - (void) handler_arg; - (void) persistence; - - LOG(WARNING, _("observe persistence not compiled in")); - return _avs_coap_err(AVS_COAP_ERR_FEATURE_DISABLED); -} - # endif // WITH_AVS_COAP_OBSERVE_PERSISTENCE #endif // WITH_AVS_COAP_OBSERVE diff --git a/deps/avs_coap/tests/udp/streaming_observe.c b/deps/avs_coap/tests/udp/streaming_observe.c index fda51c2d..3b8e5c67 100644 --- a/deps/avs_coap/tests/udp/streaming_observe.c +++ b/deps/avs_coap/tests/udp/streaming_observe.c @@ -945,8 +945,12 @@ AVS_UNIT_TEST(observe_persistence, simple) { avs_persistence_context_t persistence = avs_persistence_restore_context_create(stream); - ASSERT_OK(avs_coap_observe_restore(env.coap_ctx, on_observe_cancel, - &env, &persistence)); + avs_coap_observe_id_t restored_id; + ASSERT_OK(avs_coap_observe_restore_with_id(env.coap_ctx, + on_observe_cancel, &env, + &restored_id, &persistence)); + ASSERT_TRUE( + avs_coap_token_equal(&observe_id.token, &restored_id.token)); avs_net_socket_t *socket = NULL; avs_unit_mocksock_create_datagram(&socket); diff --git a/deps/avs_commons b/deps/avs_commons index 1a1a5112..ebcc5a7a 160000 --- a/deps/avs_commons +++ b/deps/avs_commons @@ -1 +1 @@ -Subproject commit 1a1a5112bd41b33c139e0e69d6a413d508c6659f +Subproject commit ebcc5a7a49fde3566d83c2453c15bd273b3c2d00 diff --git a/doc/sphinx/source/FirmwareUpdateTutorial/FU-SecureDownloads.rst b/doc/sphinx/source/FirmwareUpdateTutorial/FU-SecureDownloads.rst index e12b80f0..0e4e0e8b 100644 --- a/doc/sphinx/source/FirmwareUpdateTutorial/FU-SecureDownloads.rst +++ b/doc/sphinx/source/FirmwareUpdateTutorial/FU-SecureDownloads.rst @@ -127,7 +127,7 @@ After populating the ``avs_net_psk_info_t`` structure, we may use: avs_net_security_info_t avs_net_security_info_from_psk(avs_net_psk_info_t psk); -to convert into into ``avs_net_security_info_t``, as in the following example: +to convert into ``avs_net_security_info_t``, as in the following example: .. code-block:: c @@ -310,7 +310,7 @@ by the user: } anjay_fw_update_handlers_t; Now, the ``anjay_fw_update_get_security_config_t`` job is to fill -``anjay_security_config_t`` properly. This structure consists of three fields: +``anjay_security_config_t`` properly. This structure consists of four fields: .. highlight:: c .. snippet-source:: include_public/anjay/core.h @@ -348,7 +348,8 @@ Now, the ``anjay_fw_update_get_security_config_t`` job is to fill We've already seen in previous sections how to configure ``security_info``. Also, for now there is no need to worry about -``dane_tlsa_record`` or ``tls_ciphersuites`` - they can be reset to zero. +``dane_tlsa_record``, ``tls_ciphersuites`` and ``server_name_indication`` - they can be +reset to zero. Implementation ^^^^^^^^^^^^^^ diff --git a/example_configs/embedded_lwm2m10/avsystem/commons/avs_commons_config.h b/example_configs/embedded_lwm2m10/avsystem/commons/avs_commons_config.h index 71c20003..375328bc 100644 --- a/example_configs/embedded_lwm2m10/avsystem/commons/avs_commons_config.h +++ b/example_configs/embedded_lwm2m10/avsystem/commons/avs_commons_config.h @@ -429,6 +429,16 @@ */ /* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE */ +/** + * Enables use of the psa_generate_random() function as the default + * random number generator when using the Mbed TLS crypto backend, instead of + * CTR-DRBG seeded by the Mbed TLS entropy pool. + * + * It's meaningful only when @ref AVS_COMMONS_WITH_MBEDTLS is enabled. However, + * it is independent from the above PSA engine settings. + */ +/* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_RNG */ + /** * Is the dlsym() function available? * diff --git a/example_configs/embedded_lwm2m11/avsystem/commons/avs_commons_config.h b/example_configs/embedded_lwm2m11/avsystem/commons/avs_commons_config.h index 71c20003..375328bc 100644 --- a/example_configs/embedded_lwm2m11/avsystem/commons/avs_commons_config.h +++ b/example_configs/embedded_lwm2m11/avsystem/commons/avs_commons_config.h @@ -429,6 +429,16 @@ */ /* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE */ +/** + * Enables use of the psa_generate_random() function as the default + * random number generator when using the Mbed TLS crypto backend, instead of + * CTR-DRBG seeded by the Mbed TLS entropy pool. + * + * It's meaningful only when @ref AVS_COMMONS_WITH_MBEDTLS is enabled. However, + * it is independent from the above PSA engine settings. + */ +/* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_RNG */ + /** * Is the dlsym() function available? * diff --git a/example_configs/linux_lwm2m10/avsystem/commons/avs_commons_config.h b/example_configs/linux_lwm2m10/avsystem/commons/avs_commons_config.h index 9b3ecd21..1039aa80 100644 --- a/example_configs/linux_lwm2m10/avsystem/commons/avs_commons_config.h +++ b/example_configs/linux_lwm2m10/avsystem/commons/avs_commons_config.h @@ -429,6 +429,16 @@ */ /* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE */ +/** + * Enables use of the psa_generate_random() function as the default + * random number generator when using the Mbed TLS crypto backend, instead of + * CTR-DRBG seeded by the Mbed TLS entropy pool. + * + * It's meaningful only when @ref AVS_COMMONS_WITH_MBEDTLS is enabled. However, + * it is independent from the above PSA engine settings. + */ +/* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_RNG */ + /** * Is the dlsym() function available? * diff --git a/example_configs/linux_lwm2m11/avsystem/commons/avs_commons_config.h b/example_configs/linux_lwm2m11/avsystem/commons/avs_commons_config.h index 9b3ecd21..1039aa80 100644 --- a/example_configs/linux_lwm2m11/avsystem/commons/avs_commons_config.h +++ b/example_configs/linux_lwm2m11/avsystem/commons/avs_commons_config.h @@ -429,6 +429,16 @@ */ /* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE */ +/** + * Enables use of the psa_generate_random() function as the default + * random number generator when using the Mbed TLS crypto backend, instead of + * CTR-DRBG seeded by the Mbed TLS entropy pool. + * + * It's meaningful only when @ref AVS_COMMONS_WITH_MBEDTLS is enabled. However, + * it is independent from the above PSA engine settings. + */ +/* #undef AVS_COMMONS_WITH_MBEDTLS_PSA_RNG */ + /** * Is the dlsym() function available? * diff --git a/src/anjay_config_log.h b/src/anjay_config_log.h index 6f993089..2df76d57 100644 --- a/src/anjay_config_log.h +++ b/src/anjay_config_log.h @@ -640,6 +640,11 @@ static inline void _anjay_log_feature_list(void) { #else // AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE _anjay_log(anjay, TRACE, "AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE = OFF"); #endif // AVS_COMMONS_WITH_MBEDTLS_PSA_ENGINE_PROTECTED_STORAGE +#ifdef AVS_COMMONS_WITH_MBEDTLS_PSA_RNG + _anjay_log(anjay, TRACE, "AVS_COMMONS_WITH_MBEDTLS_PSA_RNG = ON"); +#else // AVS_COMMONS_WITH_MBEDTLS_PSA_RNG + _anjay_log(anjay, TRACE, "AVS_COMMONS_WITH_MBEDTLS_PSA_RNG = OFF"); +#endif // AVS_COMMONS_WITH_MBEDTLS_PSA_RNG #ifdef AVS_COMMONS_WITH_MICRO_LOGS _anjay_log(anjay, TRACE, "AVS_COMMONS_WITH_MICRO_LOGS = ON"); #else // AVS_COMMONS_WITH_MICRO_LOGS diff --git a/src/anjay_modules/anjay_utils_core.h b/src/anjay_modules/anjay_utils_core.h index 867134ef..ef9ff9f3 100644 --- a/src/anjay_modules/anjay_utils_core.h +++ b/src/anjay_modules/anjay_utils_core.h @@ -424,6 +424,8 @@ bool _anjay_ongoing_registration_exists_unlocked(anjay_unlocked_t *anjay); avs_sched_t *_anjay_get_scheduler_unlocked(anjay_unlocked_t *anjay); +void _anjay_log_oom(void); + VISIBILITY_PRIVATE_HEADER_END #endif /* ANJAY_INCLUDE_ANJAY_MODULES_UTILS_CORE_H */ diff --git a/src/core/anjay_access_utils.c b/src/core/anjay_access_utils.c index a322a06a..b98929cf 100644 --- a/src/core/anjay_access_utils.c +++ b/src/core/anjay_access_utils.c @@ -328,38 +328,62 @@ static bool is_single_ssid_environment(anjay_unlocked_t *anjay) { #endif // ANJAY_WITH_ACCESS_CONTROL -bool _anjay_instance_action_allowed(anjay_unlocked_t *anjay, - const anjay_action_info_t *info) { +anjay_instance_action_allowed_stateless_result_t +_anjay_instance_action_allowed_stateless(anjay_unlocked_t *anjay, + const anjay_action_info_t *info) { if (info->oid == ANJAY_DM_OID_SECURITY) { - return false; + return ANJAY_INSTANCE_ACTION_DISALLOWED; } assert(info->iid != ANJAY_ID_INVALID || info->action == ANJAY_ACTION_CREATE); #ifndef ANJAY_WITH_ACCESS_CONTROL - return true; + return ANJAY_INSTANCE_ACTION_ALLOWED; #else if (info->ssid == ANJAY_SSID_BOOTSTRAP) { // Access Control is not applicable to Bootstrap Server - return true; + return ANJAY_INSTANCE_ACTION_ALLOWED; } if (info->action == ANJAY_ACTION_DISCOVER) { - return true; + return ANJAY_INSTANCE_ACTION_ALLOWED; } if (!get_access_control(anjay) || is_single_ssid_environment(anjay)) { - return true; + return ANJAY_INSTANCE_ACTION_ALLOWED; } if (info->oid == ANJAY_DM_OID_ACCESS_CONTROL) { if (info->action == ANJAY_ACTION_READ || info->action == ANJAY_ACTION_WRITE_ATTRIBUTES) { - return true; + return ANJAY_INSTANCE_ACTION_ALLOWED; } else if (info->action == ANJAY_ACTION_CREATE || info->action == ANJAY_ACTION_DELETE) { - return false; + return ANJAY_INSTANCE_ACTION_DISALLOWED; } + } + + return ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK; +#endif // ANJAY_WITH_ACCESS_CONTROL +} + +#ifdef ANJAY_WITH_ACCESS_CONTROL +bool _anjay_instance_action_allowed_by_acl(anjay_unlocked_t *anjay, + const anjay_action_info_t *info) { + assert(info->oid != ANJAY_DM_OID_SECURITY); + assert(info->iid != ANJAY_ID_INVALID + || info->action == ANJAY_ACTION_CREATE); + assert(info->ssid != ANJAY_SSID_BOOTSTRAP); + assert(info->action != ANJAY_ACTION_DISCOVER); + assert(get_access_control(anjay)); + assert(!is_single_ssid_environment(anjay)); + + if (info->oid == ANJAY_DM_OID_ACCESS_CONTROL) { + assert(info->action != ANJAY_ACTION_READ); + assert(info->action != ANJAY_ACTION_WRITE_ATTRIBUTES); + assert(info->action != ANJAY_ACTION_CREATE); + assert(info->action != ANJAY_ACTION_DELETE); + anjay_ssid_t owner; if (read_u16(anjay, info->iid, ANJAY_DM_RID_ACCESS_CONTROL_OWNER, &owner)) { @@ -389,7 +413,23 @@ bool _anjay_instance_action_allowed(anjay_unlocked_t *anjay, AVS_UNREACHABLE("invalid enum value"); return false; } +} #endif // ANJAY_WITH_ACCESS_CONTROL + +bool _anjay_instance_action_allowed(anjay_unlocked_t *anjay, + const anjay_action_info_t *info) { + switch (_anjay_instance_action_allowed_stateless(anjay, info)) { + case ANJAY_INSTANCE_ACTION_DISALLOWED: + return false; + case ANJAY_INSTANCE_ACTION_ALLOWED: + return true; +#ifdef ANJAY_WITH_ACCESS_CONTROL + case ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK: + return _anjay_instance_action_allowed_by_acl(anjay, info); +#endif // ANJAY_WITH_ACCESS_CONTROL + } + AVS_UNREACHABLE("invalid enum value"); + return false; } #ifdef ANJAY_WITH_ACCESS_CONTROL @@ -456,7 +496,7 @@ enumerate_valid_ssids_clb(anjay_unlocked_t *anjay, return 0; } if (!AVS_LIST_INSERT_NEW(anjay_ssid_t, insert_ptr)) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } **insert_ptr = ssid; @@ -592,7 +632,7 @@ process_orphaned_instances_clb(anjay_unlocked_t *anjay, assert(!*args->orphaned_instance_list_append_ptr); if (!(*args->orphaned_instance_list_append_ptr = AVS_LIST_NEW_ELEMENT(orphaned_instance_info_t))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); result = -1; goto finish; } @@ -777,7 +817,7 @@ int _anjay_acl_ref_validate_inst_ref(anjay_unlocked_t *anjay, acl_ref_validation_object_info_t *object_info = get_or_create_validation_object_info(anjay, obj, ctx); if (!object_info) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } AVS_LIST(anjay_iid_t) *allowed_iid_ptr = &object_info->allowed_iids; @@ -816,7 +856,7 @@ enumerate_instances_to_remove_clb(anjay_unlocked_t *anjay, && _anjay_acl_ref_validate_inst_ref(anjay, &args->validation_ctx, target_oid, target_iid)) { if (!AVS_LIST_INSERT_NEW(anjay_iid_t, &args->iids_to_remove)) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } *args->iids_to_remove = iid; diff --git a/src/core/anjay_access_utils_private.h b/src/core/anjay_access_utils_private.h index 0b73f72d..55b7c8b5 100644 --- a/src/core/anjay_access_utils_private.h +++ b/src/core/anjay_access_utils_private.h @@ -22,6 +22,14 @@ typedef struct { anjay_request_action_t action; } anjay_action_info_t; +typedef enum { + ANJAY_INSTANCE_ACTION_DISALLOWED, + ANJAY_INSTANCE_ACTION_ALLOWED, +#ifdef ANJAY_WITH_ACCESS_CONTROL + ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK +#endif // ANJAY_WITH_ACCESS_CONTROL +} anjay_instance_action_allowed_stateless_result_t; + /** * Checks whether an operation described by the @p info on a non-restricted * Object is allowed. Security checks for restricted objects shall be performed @@ -36,6 +44,35 @@ typedef struct { bool _anjay_instance_action_allowed(anjay_unlocked_t *anjay, const anjay_action_info_t *info); +/** + * Checks whether an operation described by the @p info on a non-restricted + * Object is allowed, but only if that can be determined without accessing the + * data model. + * + * Returns @ref ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK if it is not possible. + */ +anjay_instance_action_allowed_stateless_result_t +_anjay_instance_action_allowed_stateless(anjay_unlocked_t *anjay, + const anjay_action_info_t *info); + +#ifdef ANJAY_WITH_ACCESS_CONTROL +/** + * Accesses the data model to check whether an operation described by @p info + * is allowed. + * + * May only be called on an @p info object previously checked using @ref + * _anjay_instance_action_allowed_stateless which returned @ref + * ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK result. The behavior is undefined + * otherwise. + * + * @ref _anjay_instance_action_allowed_stateless and @ref + * _anjay_instance_action_allowed_by_acl together shall have identical semantics + * to @ref _anjay_instance_action_allowed. + */ +bool _anjay_instance_action_allowed_by_acl(anjay_unlocked_t *anjay, + const anjay_action_info_t *info); +#endif // ANJAY_WITH_ACCESS_CONTROL + /** * Performs implicit creations and deletions of Access Control object instances * according to data model changes. diff --git a/src/core/anjay_bootstrap_core.c b/src/core/anjay_bootstrap_core.c index 09348842..a4c9250f 100644 --- a/src/core/anjay_bootstrap_core.c +++ b/src/core/anjay_bootstrap_core.c @@ -889,7 +889,7 @@ static int bootstrap_read(anjay_connection_ref_t bootstrap_connection, anjay_unlocked_output_ctx_t *out_ctx = NULL; (void) ((result = _anjay_output_dynamic_construct( &out_ctx, response_stream, &request->uri, details.format, - ANJAY_ACTION_READ)) + NULL, ANJAY_ACTION_READ)) || (result = _anjay_dm_read_and_destroy_ctx(anjay, obj, &path_info, ANJAY_SSID_BOOTSTRAP, &out_ctx))); diff --git a/src/core/anjay_core.c b/src/core/anjay_core.c index 2931776f..b68aacf3 100644 --- a/src/core/anjay_core.c +++ b/src/core/anjay_core.c @@ -47,7 +47,7 @@ VISIBILITY_SOURCE_BEGIN #ifndef ANJAY_VERSION -# define ANJAY_VERSION "3.6.0" +# define ANJAY_VERSION "3.6.1" #endif // ANJAY_VERSION #ifdef ANJAY_WITH_LWM2M11 @@ -61,7 +61,7 @@ static int init_anjay(anjay_unlocked_t *anjay, const anjay_configuration_t *config) { #ifdef ANJAY_WITH_THREAD_SAFETY if (!(anjay->coap_sched = avs_sched_new("Anjay CoAP", NULL))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } #endif // ANJAY_WITH_THREAD_SAFETY @@ -149,7 +149,7 @@ static int init_anjay(anjay_unlocked_t *anjay, anjay->udp_response_cache = avs_coap_udp_response_cache_create(config->msg_cache_size); if (!anjay->udp_response_cache) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } } @@ -206,12 +206,12 @@ static int init_anjay(anjay_unlocked_t *anjay, anjay->in_shared_buffer = avs_shared_buffer_new(config->in_buffer_size); if (!anjay->in_shared_buffer) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } anjay->out_shared_buffer = avs_shared_buffer_new(config->out_buffer_size); if (!anjay->out_shared_buffer) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } @@ -302,7 +302,7 @@ static anjay_t *alloc_anjay(void) { #endif // ANJAY_WITH_THREAD_SAFETY anjay_t *out = (anjay_t *) avs_calloc(1, alloc_size); if (!out) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } #ifdef ANJAY_WITH_THREAD_SAFETY @@ -317,7 +317,7 @@ static anjay_t *alloc_anjay(void) { anjay_unlocked_t *anjay = out; #endif // ANJAY_WITH_THREAD_SAFETY if (!(anjay->sched = avs_sched_new("Anjay", out))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); #ifdef ANJAY_WITH_THREAD_SAFETY avs_mutex_cleanup(&out->mutex); #endif // ANJAY_WITH_THREAD_SAFETY diff --git a/src/core/anjay_dm_core.c b/src/core/anjay_dm_core.c index ef74ec32..2cc54440 100644 --- a/src/core/anjay_dm_core.c +++ b/src/core/anjay_dm_core.c @@ -170,7 +170,7 @@ int anjay_register_object(anjay_t *anjay_locked, AVS_LIST(anjay_dm_installed_object_t) new_elem = AVS_LIST_NEW_ELEMENT(anjay_dm_installed_object_t); if (!new_elem) { - dm_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } @@ -869,7 +869,7 @@ static int query_dm_instance(anjay_unlocked_t *anjay, AVS_LIST(anjay_iid_t) new_instance = AVS_LIST_NEW_ELEMENT(anjay_iid_t); if (!new_instance) { - dm_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } AVS_LIST_INSERT(*instance_insert_ptr, new_instance); diff --git a/src/core/anjay_event_loop.c b/src/core/anjay_event_loop.c index d4a2ac8e..431ed1eb 100644 --- a/src/core/anjay_event_loop.c +++ b/src/core/anjay_event_loop.c @@ -114,7 +114,7 @@ static handle_sockets_result_t handle_sockets(event_loop_state_t *state) { state->pollfds = pollfds_new; state->pollfds_size = numsocks; } else if (numsocks > state->pollfds_size) { - anjay_log(ERROR, "Out of memory in anjay_event_loop_run()"); + _anjay_log_oom(); result = HANDLE_SOCKETS_ERROR; } } diff --git a/src/core/anjay_io_core.h b/src/core/anjay_io_core.h index a89dd288..246a6a82 100644 --- a/src/core/anjay_io_core.h +++ b/src/core/anjay_io_core.h @@ -38,6 +38,7 @@ int _anjay_output_dynamic_construct(anjay_unlocked_output_ctx_t **out_ctx, avs_stream_t *stream, const anjay_uri_path_t *uri, uint16_t format, + const size_t *items_count, anjay_request_action_t action); #ifdef ANJAY_WITH_LEGACY_CONTENT_FORMAT_SUPPORT @@ -192,8 +193,11 @@ _anjay_output_tlv_create(avs_stream_t *stream, const anjay_uri_path_t *uri); #if defined(ANJAY_WITH_LWM2M_JSON) || defined(ANJAY_WITH_SENML_JSON) \ || defined(ANJAY_WITH_CBOR) -anjay_unlocked_output_ctx_t *_anjay_output_senml_like_create( - avs_stream_t *stream, const anjay_uri_path_t *uri, uint16_t format); +anjay_unlocked_output_ctx_t * +_anjay_output_senml_like_create(avs_stream_t *stream, + const anjay_uri_path_t *uri, + uint16_t format, + const size_t *items_count); #endif int _anjay_output_bytes_begin(anjay_unlocked_output_ctx_t *ctx, @@ -278,7 +282,8 @@ uint16_t _anjay_default_simple_format(anjay_unlocked_t *anjay, int _anjay_output_dynamic_send_construct(anjay_unlocked_output_ctx_t **out_ctx, avs_stream_t *stream, const anjay_uri_path_t *uri, - uint16_t format); + uint16_t format, + const size_t *items_count); #endif // ANJAY_WITH_SEND VISIBILITY_PRIVATE_HEADER_END diff --git a/src/core/anjay_lwm2m_send.c b/src/core/anjay_lwm2m_send.c index cf32d805..0db0144e 100644 --- a/src/core/anjay_lwm2m_send.c +++ b/src/core/anjay_lwm2m_send.c @@ -259,7 +259,7 @@ create_exchange(anjay_unlocked_t *anjay, AVS_LIST(anjay_send_entry_t) entry = AVS_LIST_NEW_ELEMENT(anjay_send_entry_t); if (!entry) { - send_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } entry->anjay = anjay; @@ -336,11 +336,17 @@ static avs_error_t start_send_exchange(anjay_send_entry_t *entry, goto finish; } + size_t item_count; if (!(entry->exchange_status.memstream = avs_stream_membuf_create()) || (_anjay_output_dynamic_send_construct( &entry->exchange_status.out_ctx, entry->exchange_status.memstream, &base_path, - content_format))) { + content_format, + _anjay_batch_outputable_item_count( + entry->anjay, entry->payload_batch, + entry->target_ssid, &item_count) + ? NULL + : &item_count))) { send_log(ERROR, _("could not create output context")); err = avs_errno(AVS_ENOMEM); goto finish; diff --git a/src/core/anjay_notify.c b/src/core/anjay_notify.c index 5700ce69..e6034948 100644 --- a/src/core/anjay_notify.c +++ b/src/core/anjay_notify.c @@ -248,12 +248,12 @@ int _anjay_notify_queue_instance_created(anjay_notify_queue_t *out_queue, AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = find_or_create_object_entry(out_queue, oid); if (!entry_ptr) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } if (add_entry_to_iid_set( &(*entry_ptr)->instance_set_changes.known_added_iids, iid)) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); delete_notify_queue_object_entry_if_empty(entry_ptr); return -1; } @@ -267,7 +267,7 @@ int _anjay_notify_queue_instance_removed(anjay_notify_queue_t *out_queue, AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = find_or_create_object_entry(out_queue, oid); if (!entry_ptr) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } remove_entry_from_iid_set( @@ -281,7 +281,7 @@ int _anjay_notify_queue_instance_set_unknown_change( AVS_LIST(anjay_notify_queue_object_entry_t) *entry_ptr = find_or_create_object_entry(out_queue, oid); if (!entry_ptr) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } (*entry_ptr)->instance_set_changes.instance_set_changed = true; @@ -305,7 +305,7 @@ int _anjay_notify_queue_resource_change(anjay_notify_queue_t *out_queue, AVS_LIST(anjay_notify_queue_object_entry_t) *obj_entry_ptr = find_or_create_object_entry(out_queue, oid); if (!obj_entry_ptr) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } anjay_notify_queue_resource_entry_t new_entry = { @@ -323,7 +323,7 @@ int _anjay_notify_queue_resource_change(anjay_notify_queue_t *out_queue, } if (!AVS_LIST_INSERT_NEW(anjay_notify_queue_resource_entry_t, res_entry_ptr)) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); if (!(*obj_entry_ptr)->instance_set_changes.instance_set_changed && !(*obj_entry_ptr)->resources_changed) { AVS_LIST_DELETE(obj_entry_ptr); diff --git a/src/core/anjay_utils_core.c b/src/core/anjay_utils_core.c index 84c10c5f..b75876ce 100644 --- a/src/core/anjay_utils_core.c +++ b/src/core/anjay_utils_core.c @@ -59,7 +59,7 @@ static int url_parse_chunks(const char **url, AVS_LIST(anjay_string_t) chunk = (AVS_LIST( anjay_string_t)) AVS_LIST_NEW_BUFFER(chunk_len + 1); if (!chunk) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } AVS_LIST_APPEND(out_chunks, chunk); @@ -195,7 +195,7 @@ AVS_LIST(const anjay_string_t) _anjay_make_string_list(const char *string, size_t len = strlen(str) + 1; if (!(*strings_list_endptr = (AVS_LIST(anjay_string_t)) AVS_LIST_NEW_BUFFER(len))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); AVS_LIST_CLEAR(&strings_list); break; } @@ -455,7 +455,7 @@ int _anjay_copy_tls_ciphersuites(avs_net_socket_tls_ciphersuites_t *dest, if (src->num_ids) { if (!(dest->ids = (uint32_t *) avs_calloc(src->num_ids, sizeof(*dest->ids)))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } memcpy(dest->ids, src->ids, src->num_ids * sizeof(*src->ids)); @@ -821,6 +821,10 @@ int _anjay_safe_strtod(const char *in, double *value) { // || defined(ANJAY_WITH_CORE_PERSISTENCE)) +void _anjay_log_oom(void) { + anjay_log(ERROR, _("out of memory")); +} + #ifdef ANJAY_TEST # include "tests/core/utils.c" #endif // ANJAY_TEST diff --git a/src/core/attr_storage/anjay_attr_storage.c b/src/core/attr_storage/anjay_attr_storage.c index 97f7d85e..3a814dc3 100644 --- a/src/core/attr_storage/anjay_attr_storage.c +++ b/src/core/attr_storage/anjay_attr_storage.c @@ -90,7 +90,7 @@ find_or_create_entry_impl(AVS_LIST(void) *children_list_ptr, if (allow_create) { AVS_LIST(void) new_entry = AVS_LIST_NEW_BUFFER(entry_size); if (!new_entry) { - as_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } *(uint16_t *) new_entry = id; @@ -458,7 +458,7 @@ static int write_attrs_impl(anjay_attr_storage_t *as, // entry does not exist, creating AVS_LIST(void) new_attrs = AVS_LIST_NEW_BUFFER(element_size); if (!new_attrs) { - as_log(ERROR, _("out of memory")); + _anjay_log_oom(); return ANJAY_ERR_INTERNAL; } *get_ssid_ptr(new_attrs) = ssid; diff --git a/src/core/dm/anjay_dm_handlers.c b/src/core/dm/anjay_dm_handlers.c index 6b4ba4c4..bdb59754 100644 --- a/src/core/dm/anjay_dm_handlers.c +++ b/src/core/dm/anjay_dm_handlers.c @@ -976,7 +976,7 @@ int _anjay_dm_transaction_include_object( AVS_LIST(const anjay_dm_installed_object_t *) new_entry = AVS_LIST_NEW_ELEMENT(const anjay_dm_installed_object_t *); if (!new_entry) { - dm_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } *new_entry = obj_ptr; diff --git a/src/core/dm/anjay_dm_read.c b/src/core/dm/anjay_dm_read.c index c74039aa..db8ffb6f 100644 --- a/src/core/dm/anjay_dm_read.c +++ b/src/core/dm/anjay_dm_read.c @@ -385,7 +385,7 @@ int _anjay_dm_read_or_observe(anjay_connection_ref_t connection, anjay_unlocked_output_ctx_t *out_ctx = NULL; if ((result = _anjay_output_dynamic_construct(&out_ctx, response_stream, &request->uri, details.format, - ANJAY_ACTION_READ))) { + NULL, ANJAY_ACTION_READ))) { return result; } return _anjay_dm_read_and_destroy_ctx(anjay, obj, &path_info, @@ -604,7 +604,7 @@ int _anjay_dm_read_or_observe_composite(anjay_connection_ref_t connection, anjay_unlocked_output_ctx_t *out_ctx = NULL; (void) ((result = _anjay_output_dynamic_construct( &out_ctx, response_stream, &root_path, details.format, - ANJAY_ACTION_READ_COMPOSITE))); + NULL, ANJAY_ACTION_READ_COMPOSITE))); while (!result && cached_paths) { const anjay_uri_path_t path = *cached_paths; AVS_LIST_DELETE(&cached_paths); diff --git a/src/core/dm/anjay_modules.c b/src/core/dm/anjay_modules.c index aa958db2..d3707d0d 100644 --- a/src/core/dm/anjay_modules.c +++ b/src/core/dm/anjay_modules.c @@ -40,7 +40,7 @@ int _anjay_dm_module_install(anjay_unlocked_t *anjay, AVS_LIST(anjay_dm_installed_module_t) new_entry = AVS_LIST_NEW_ELEMENT(anjay_dm_installed_module_t); if (!new_entry) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } new_entry->deleter = module_deleter; diff --git a/src/core/downloader/anjay_coap.c b/src/core/downloader/anjay_coap.c index dd18f00c..d78baa3a 100644 --- a/src/core/downloader/anjay_coap.c +++ b/src/core/downloader/anjay_coap.c @@ -519,7 +519,7 @@ _anjay_downloader_coap_ctx_new(anjay_downloader_t *dl, AVS_LIST(anjay_coap_download_ctx_t) ctx = AVS_LIST_NEW_ELEMENT(anjay_coap_download_ctx_t); if (!ctx) { - dl_log(ERROR, _("out of memory")); + _anjay_log_oom(); return avs_errno(AVS_ENOMEM); } if (forced_coap_ctx) { diff --git a/src/core/downloader/anjay_http.c b/src/core/downloader/anjay_http.c index a68e7a09..3689a816 100644 --- a/src/core/downloader/anjay_http.c +++ b/src/core/downloader/anjay_http.c @@ -548,7 +548,7 @@ _anjay_downloader_http_ctx_new(anjay_downloader_t *dl, AVS_LIST(anjay_http_download_ctx_t) ctx = AVS_LIST_NEW_ELEMENT(anjay_http_download_ctx_t); if (!ctx) { - dl_log(ERROR, _("out of memory")); + _anjay_log_oom(); return avs_errno(AVS_ENOMEM); } diff --git a/src/core/io/anjay_batch_builder.c b/src/core/io/anjay_batch_builder.c index 09510353..48184fe1 100644 --- a/src/core/io/anjay_batch_builder.c +++ b/src/core/io/anjay_batch_builder.c @@ -745,19 +745,6 @@ static int serialize_batch_entry(const anjay_batch_entry_t *entry, } } -static bool is_server_allowed_to_read(anjay_unlocked_t *anjay, - anjay_oid_t oid, - anjay_iid_t iid, - anjay_ssid_t ssid) { - const anjay_action_info_t action_info = { - .oid = oid, - .iid = iid, - .ssid = ssid, - .action = ANJAY_ACTION_READ - }; - return _anjay_instance_action_allowed(anjay, &action_info); -} - int _anjay_batch_data_output(anjay_unlocked_t *anjay, const anjay_batch_t *batch, anjay_ssid_t target_ssid, @@ -788,9 +775,13 @@ int _anjay_batch_data_output_entry( assert(AVS_LIST_FIND_PTR(&batch->list, it) != NULL); } while (it - && !is_server_allowed_to_read(anjay, it->path.ids[ANJAY_ID_OID], - it->path.ids[ANJAY_ID_IID], - target_ssid)) { + && !_anjay_instance_action_allowed( + anjay, &(const anjay_action_info_t) { + .oid = it->path.ids[ANJAY_ID_OID], + .iid = it->path.ids[ANJAY_ID_IID], + .ssid = target_ssid, + .action = ANJAY_ACTION_READ + })) { AVS_LIST_ADVANCE((AVS_LIST(anjay_batch_entry_t) *) (intptr_t) &it); } int result = 0; @@ -865,6 +856,37 @@ bool _anjay_batch_data_requires_hierarchical_format( return false; } +int _anjay_batch_outputable_item_count(anjay_unlocked_t *anjay, + const anjay_batch_t *batch, + anjay_ssid_t target_ssid, + size_t *out_count) { + size_t count = 0; + if (batch) { + AVS_LIST(anjay_batch_entry_t) it; + AVS_LIST_FOREACH(it, batch->list) { + anjay_instance_action_allowed_stateless_result_t result = + _anjay_instance_action_allowed_stateless( + anjay, &(const anjay_action_info_t) { + .oid = it->path.ids[ANJAY_ID_OID], + .iid = it->path.ids[ANJAY_ID_IID], + .ssid = target_ssid, + .action = ANJAY_ACTION_READ + }); +# ifdef ANJAY_WITH_ACCESS_CONTROL + if (result == ANJAY_INSTANCE_ACTION_NEEDS_ACL_CHECK) { + return -1; + } +# endif // ANJAY_WITH_ACCESS_CONTROL + if (result == ANJAY_INSTANCE_ACTION_ALLOWED + && it->data.type != ANJAY_BATCH_DATA_START_AGGREGATE) { + ++count; + } + } + } + *out_count = count; + return 0; +} + double _anjay_batch_data_numeric_value(const anjay_batch_t *batch) { if (_anjay_batch_data_requires_hierarchical_format(batch)) { // not a simple value diff --git a/src/core/io/anjay_batch_builder.h b/src/core/io/anjay_batch_builder.h index 7ffc5acd..0195983d 100644 --- a/src/core/io/anjay_batch_builder.h +++ b/src/core/io/anjay_batch_builder.h @@ -228,6 +228,35 @@ int _anjay_batch_data_output_entry( const anjay_batch_data_output_state_t **state, anjay_unlocked_output_ctx_t *out_ctx); +/** + * Calculates the number of entries that will be generated in a SenML document + * if @ref _anjay_batch_data_output_entry is called on a given @p batch. + * + * This is calculated only if it's possible to do so without accessing the data + * model. That might not be true if the Access Control mechanism is in use, i.e. + * it is enabled and there are multiple LwM2M Server Accounts actually + * configured. + * + * @param [in] anjay Anjay object to operate on. + * + * @param [in] batch Compiled batch. + * + * @param [in] target_ssid SSID of the server for which this batch is being + * serialized. Will be used in relation to the Access + * Control mechanism. + * + * @param [out] out_count Pointer to a variable that, on successful return, + * will be filled with the calculated number of + * items. + * + * @returns 0 for success, or a negative value if the count depends on the data + * in the Access Control object. + */ +int _anjay_batch_outputable_item_count(anjay_unlocked_t *anjay, + const anjay_batch_t *batch, + anjay_ssid_t target_ssid, + size_t *out_count); + /** * Returns whether two batches have exactly the same data. * diff --git a/src/core/io/anjay_dynamic.c b/src/core/io/anjay_dynamic.c index 9af6f9ee..9fc6a16a 100644 --- a/src/core/io/anjay_dynamic.c +++ b/src/core/io/anjay_dynamic.c @@ -27,52 +27,65 @@ VISIBILITY_SOURCE_BEGIN /////////////////////////////////////////////////////////////////////// ENCODING static anjay_unlocked_output_ctx_t *spawn_opaque(avs_stream_t *stream, - const anjay_uri_path_t *uri) { + const anjay_uri_path_t *uri, + const size_t *items_count) { (void) uri; + (void) items_count; return _anjay_output_opaque_create(stream); } #ifndef ANJAY_WITHOUT_PLAINTEXT static anjay_unlocked_output_ctx_t *spawn_text(avs_stream_t *stream, - const anjay_uri_path_t *uri) { + const anjay_uri_path_t *uri, + const size_t *items_count) { (void) uri; + (void) items_count; return _anjay_output_text_create(stream); } #endif // ANJAY_WITHOUT_PLAINTEXT #ifndef ANJAY_WITHOUT_TLV static anjay_unlocked_output_ctx_t *spawn_tlv(avs_stream_t *stream, - const anjay_uri_path_t *uri) { + const anjay_uri_path_t *uri, + const size_t *items_count) { + (void) items_count; return _anjay_output_tlv_create(stream, uri); } #endif // ANJAY_WITHOUT_TLV #ifdef ANJAY_WITH_LWM2M_JSON static anjay_unlocked_output_ctx_t *spawn_json(avs_stream_t *stream, - const anjay_uri_path_t *uri) { - return _anjay_output_senml_like_create(stream, uri, - AVS_COAP_FORMAT_OMA_LWM2M_JSON); + const anjay_uri_path_t *uri, + const size_t *items_count) { + return _anjay_output_senml_like_create( + stream, uri, AVS_COAP_FORMAT_OMA_LWM2M_JSON, items_count); } #endif // ANJAY_WITH_LWM2M_JSON #ifdef ANJAY_WITH_SENML_JSON static anjay_unlocked_output_ctx_t * -spawn_senml_json(avs_stream_t *stream, const anjay_uri_path_t *uri) { - return _anjay_output_senml_like_create(stream, uri, - AVS_COAP_FORMAT_SENML_JSON); +spawn_senml_json(avs_stream_t *stream, + const anjay_uri_path_t *uri, + const size_t *items_count) { + return _anjay_output_senml_like_create( + stream, uri, AVS_COAP_FORMAT_SENML_JSON, items_count); } #endif // ANJAY_WITH_SENML_JSON #ifdef ANJAY_WITH_CBOR static anjay_unlocked_output_ctx_t * -spawn_senml_cbor(avs_stream_t *stream, const anjay_uri_path_t *uri) { - return _anjay_output_senml_like_create(stream, uri, - AVS_COAP_FORMAT_SENML_CBOR); +spawn_senml_cbor(avs_stream_t *stream, + const anjay_uri_path_t *uri, + const size_t *items_count) { + return _anjay_output_senml_like_create( + stream, uri, AVS_COAP_FORMAT_SENML_CBOR, items_count); } static anjay_unlocked_output_ctx_t *spawn_cbor(avs_stream_t *stream, - const anjay_uri_path_t *uri) { + const anjay_uri_path_t *uri, + const size_t *items_count) { (void) uri; + (void) items_count; return _anjay_output_cbor_create(stream); } @@ -82,7 +95,9 @@ typedef struct { uint16_t format; anjay_input_ctx_constructor_t *input_ctx_constructor; anjay_unlocked_output_ctx_t *(*output_ctx_spawn_func)( - avs_stream_t *stream, const anjay_uri_path_t *uri); + avs_stream_t *stream, + const anjay_uri_path_t *uri, + const size_t *items_count); } dynamic_format_def_t; static const dynamic_format_def_t SUPPORTED_SIMPLE_FORMATS[] = { @@ -174,6 +189,7 @@ static int spawn_output_ctx(anjay_unlocked_output_ctx_t **out_ctx, avs_stream_t *stream, const anjay_uri_path_t *uri, uint16_t format, + const size_t *items_count, const dynamic_format_def_t *def) { if (!def || !def->output_ctx_spawn_func) { anjay_log(DEBUG, @@ -183,7 +199,7 @@ static int spawn_output_ctx(anjay_unlocked_output_ctx_t **out_ctx, return ANJAY_ERR_NOT_ACCEPTABLE; } - if (!(*out_ctx = def->output_ctx_spawn_func(stream, uri))) { + if (!(*out_ctx = def->output_ctx_spawn_func(stream, uri, items_count))) { anjay_log(DEBUG, _("Failed to spawn output context")); return ANJAY_ERR_INTERNAL; } @@ -233,6 +249,7 @@ int _anjay_output_dynamic_construct(anjay_unlocked_output_ctx_t **out_ctx, avs_stream_t *stream, const anjay_uri_path_t *uri, uint16_t format, + const size_t *items_count, anjay_request_action_t action) { if (format == AVS_COAP_FORMAT_NONE) { return -1; @@ -253,7 +270,7 @@ int _anjay_output_dynamic_construct(anjay_unlocked_output_ctx_t **out_ctx, default: break; } - return spawn_output_ctx(out_ctx, stream, uri, format, def); + return spawn_output_ctx(out_ctx, stream, uri, format, items_count, def); } /////////////////////////////////////////////////////////////////////// DECODING @@ -318,7 +335,8 @@ int _anjay_input_dynamic_construct(anjay_unlocked_input_ctx_t **out, int _anjay_output_dynamic_send_construct(anjay_unlocked_output_ctx_t **out_ctx, avs_stream_t *stream, const anjay_uri_path_t *uri, - uint16_t format) { + uint16_t format, + const size_t *items_count) { if (format == AVS_COAP_FORMAT_NONE) { return -1; } @@ -326,7 +344,7 @@ int _anjay_output_dynamic_send_construct(anjay_unlocked_output_ctx_t **out_ctx, const dynamic_format_def_t *def = find_format(SUPPORTED_SEND_FORMATS, format); - return spawn_output_ctx(out_ctx, stream, uri, format, def); + return spawn_output_ctx(out_ctx, stream, uri, format, items_count, def); } #endif // ANJAY_WITH_SEND diff --git a/src/core/io/anjay_senml_like_encoder.h b/src/core/io/anjay_senml_like_encoder.h index c4b4485b..4be7d744 100644 --- a/src/core/io/anjay_senml_like_encoder.h +++ b/src/core/io/anjay_senml_like_encoder.h @@ -104,14 +104,18 @@ int _anjay_senml_like_encoder_cleanup(anjay_senml_like_encoder_t **ctx); /** * Creates SenML CBOR encoder (content format 112). * - * @param stream Stream to encode data to. Encoder doesn't take ownership of - * stream. + * @param stream Stream to encode data to. Encoder doesn't take ownership + * of stream. + * @param items_count Pointer to a variable that specifies the number of entries + * in the outermost definite array, or NULL if not known. + * * @returns Pointer to encoder in case of success, NULL otherwise. * * In current implementation, all data are cached and written to stream during * call to _anjay_senml_like_encoder_cleanup. */ -anjay_senml_like_encoder_t *_anjay_senml_cbor_encoder_new(avs_stream_t *stream); +anjay_senml_like_encoder_t * +_anjay_senml_cbor_encoder_new(avs_stream_t *stream, const size_t *items_count); #endif // ANJAY_WITH_CBOR #ifdef ANJAY_WITH_SENML_JSON diff --git a/src/core/io/anjay_senml_like_out.c b/src/core/io/anjay_senml_like_out.c index d136dd5d..b13d73a5 100644 --- a/src/core/io/anjay_senml_like_out.c +++ b/src/core/io/anjay_senml_like_out.c @@ -286,8 +286,14 @@ static const anjay_output_ctx_vtable_t SENML_OUT_VTABLE = { .close = senml_output_close }; -anjay_unlocked_output_ctx_t *_anjay_output_senml_like_create( - avs_stream_t *stream, const anjay_uri_path_t *uri, uint16_t format) { +anjay_unlocked_output_ctx_t * +_anjay_output_senml_like_create(avs_stream_t *stream, + const anjay_uri_path_t *uri, + uint16_t format, + const size_t *items_count) { +# ifndef ANJAY_WITH_CBOR + (void) items_count; +# endif // ANJAY_WITH_CBOR senml_out_t *ctx = (senml_out_t *) avs_calloc(1, sizeof(senml_out_t)); if (!ctx) { return NULL; @@ -316,7 +322,7 @@ anjay_unlocked_output_ctx_t *_anjay_output_senml_like_create( # endif // ANJAY_WITH_SENML_JSON # ifdef ANJAY_WITH_CBOR case AVS_COAP_FORMAT_SENML_CBOR: - ctx->encoder = _anjay_senml_cbor_encoder_new(stream); + ctx->encoder = _anjay_senml_cbor_encoder_new(stream, items_count); break; # endif // ANJAY_WITH_CBOR default: diff --git a/src/core/io/cbor/anjay_senml_cbor_encoder.c b/src/core/io/cbor/anjay_senml_cbor_encoder.c index a74994b7..3c36458a 100644 --- a/src/core/io/cbor/anjay_senml_cbor_encoder.c +++ b/src/core/io/cbor/anjay_senml_cbor_encoder.c @@ -40,7 +40,8 @@ VISIBILITY_SOURCE_BEGIN typedef enum { CBOR_CONTEXT_TYPE_ROOT = 0, - CBOR_CONTEXT_TYPE_ARRAY, + CBOR_CONTEXT_TYPE_UNKNOWN_LENGTH_ARRAY, + CBOR_CONTEXT_TYPE_KNOWN_LENGTH_ARRAY, CBOR_CONTEXT_TYPE_BYTES, CBOR_CONTEXT_TYPE_MAP } cbor_context_type_t; @@ -217,7 +218,25 @@ static int cbor_definite_map_end(cbor_encoder_t *ctx) { return retval; } -static int cbor_definite_array_begin(cbor_encoder_t *ctx) { +static int cbor_known_length_definite_array_begin(cbor_encoder_t *ctx, + size_t items_count) { + assert(ctx); + cbor_encoder_internal_t *top_ctx = nested_context_top(ctx); + assert(top_ctx->context_type != CBOR_CONTEXT_TYPE_BYTES); + + cbor_encoder_internal_t *array_ctx = + nested_context_push(ctx, top_ctx->stream, + CBOR_CONTEXT_TYPE_KNOWN_LENGTH_ARRAY); + + int retval = + _anjay_cbor_ll_definite_array_begin(array_ctx->stream, items_count); + if (retval) { + nested_context_pop(ctx); + } + return retval; +} + +static int cbor_unknown_length_definite_array_begin(cbor_encoder_t *ctx) { cbor_encoder_internal_t *top_ctx = nested_context_top(ctx); assert(top_ctx->context_type != CBOR_CONTEXT_TYPE_BYTES); (void) top_ctx; @@ -227,7 +246,7 @@ static int cbor_definite_array_begin(cbor_encoder_t *ctx) { return -1; } - nested_context_push(ctx, stream, CBOR_CONTEXT_TYPE_ARRAY); + nested_context_push(ctx, stream, CBOR_CONTEXT_TYPE_UNKNOWN_LENGTH_ARRAY); return 0; } @@ -248,7 +267,9 @@ static int copy_stream(avs_stream_t *dst, avs_stream_t *src) { static int cbor_definite_array_end(cbor_encoder_t *ctx) { assert(ctx); cbor_encoder_internal_t *top_ctx = nested_context_top(ctx); - if (top_ctx->context_type != CBOR_CONTEXT_TYPE_ARRAY) { + cbor_context_type_t context_type = top_ctx->context_type; + if (context_type != CBOR_CONTEXT_TYPE_UNKNOWN_LENGTH_ARRAY + && context_type != CBOR_CONTEXT_TYPE_KNOWN_LENGTH_ARRAY) { cbor_log(DEBUG, _("trying to finish array, but it is not started")); return -1; } @@ -258,11 +279,16 @@ static int cbor_definite_array_end(cbor_encoder_t *ctx) { top_ctx = nested_context_top(ctx); - int retval; - (void) ((retval = _anjay_cbor_ll_definite_array_begin(top_ctx->stream, - entries)) - || (retval = copy_stream(top_ctx->stream, array_stream))); - avs_stream_cleanup(&array_stream); + assert((top_ctx->stream == array_stream) + == (context_type == CBOR_CONTEXT_TYPE_KNOWN_LENGTH_ARRAY)); + + int retval = 0; + if (context_type == CBOR_CONTEXT_TYPE_UNKNOWN_LENGTH_ARRAY) { + (void) ((retval = _anjay_cbor_ll_definite_array_begin(top_ctx->stream, + entries)) + || (retval = copy_stream(top_ctx->stream, array_stream))); + avs_stream_cleanup(&array_stream); + } top_ctx->size++; return retval; } @@ -437,7 +463,7 @@ static int senml_cbor_encoder_cleanup(anjay_senml_like_encoder_t **ctx_) { while (ctx->stack_size > 1) { cbor_encoder_internal_t *top_ctx = nested_context_top(ctx); - if (top_ctx->context_type == CBOR_CONTEXT_TYPE_ARRAY) { + if (top_ctx->context_type == CBOR_CONTEXT_TYPE_UNKNOWN_LENGTH_ARRAY) { avs_stream_cleanup(&top_ctx->stream); } nested_context_pop(ctx); @@ -464,7 +490,7 @@ static const anjay_senml_like_encoder_vtable_t SENML_CBOR_ENCODER_VTABLE = { }; anjay_senml_like_encoder_t * -_anjay_senml_cbor_encoder_new(avs_stream_t *stream) { +_anjay_senml_cbor_encoder_new(avs_stream_t *stream, const size_t *items_count) { if (!stream) { cbor_log(DEBUG, _("no stream provided")); return NULL; @@ -478,7 +504,13 @@ _anjay_senml_cbor_encoder_new(avs_stream_t *stream) { } nested_context_push(ctx, stream, CBOR_CONTEXT_TYPE_ROOT); - if (cbor_definite_array_begin(ctx)) { + int result; + if (items_count) { + result = cbor_known_length_definite_array_begin(ctx, *items_count); + } else { + result = cbor_unknown_length_definite_array_begin(ctx); + } + if (result) { avs_free(ctx); return NULL; } diff --git a/src/core/observe/anjay_observe_core.c b/src/core/observe/anjay_observe_core.c index 519865d5..cdb4c2eb 100644 --- a/src/core/observe/anjay_observe_core.c +++ b/src/core/observe/anjay_observe_core.c @@ -115,7 +115,7 @@ find_or_create_observe_path_entry(anjay_observe_connection_entry_t *connection, AVS_SORTED_SET_ELEM(anjay_observe_path_entry_t) new_entry = AVS_SORTED_SET_ELEM_NEW(anjay_observe_path_entry_t); if (!new_entry) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } @@ -140,7 +140,7 @@ static int add_path_to_observed_paths( AVS_LIST_INSERT_NEW(AVS_SORTED_SET_ELEM(anjay_observation_t), &observed_path->refs); if (!entry) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); if (!observed_path->refs) { AVS_SORTED_SET_DELETE_ELEM(conn->observed_paths, &observed_path); } @@ -232,7 +232,9 @@ detach_observation(anjay_observe_connection_entry_t *conn, static void cleanup_observation(anjay_observe_connection_entry_t *conn, AVS_SORTED_SET_ELEM(anjay_observation_t) observation) { - remove_from_observed_paths(conn, observation); + if (conn->observed_paths) { + remove_from_observed_paths(conn, observation); + } avs_sched_del(&observation->notify_task); if (observation->last_sent) { delete_value(_anjay_from_server(conn->conn_ref.server), @@ -243,10 +245,13 @@ cleanup_observation(anjay_observe_connection_entry_t *conn, static void cleanup_connection_without_observations_set( anjay_observe_connection_entry_t *conn) { - anjay_unlocked_t *anjay = _anjay_from_server(conn->conn_ref.server); - while (conn->unsent) { - delete_value(anjay, &conn->unsent); + if (conn->conn_ref.server) { + anjay_unlocked_t *anjay = _anjay_from_server(conn->conn_ref.server); + while (conn->unsent) { + delete_value(anjay, &conn->unsent); + } } + assert(!conn->unsent); AVS_SORTED_SET_ELEM(anjay_observation_t) observation; AVS_SORTED_SET_FOREACH(observation, conn->observations) { cleanup_observation(conn, observation); @@ -437,7 +442,7 @@ create_observation_value(const anjay_msg_details_t *details, AVS_LIST(anjay_observation_value_t) result = (AVS_LIST( anjay_observation_value_t)) AVS_LIST_NEW_BUFFER(element_size); if (!result) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } result->details = *details; @@ -714,7 +719,7 @@ create_detached_observation(const avs_coap_token_t *token, offsetof(anjay_observation_t, paths) + paths->count * sizeof(const anjay_uri_path_t)); if (!new_observation) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } memcpy((void *) (intptr_t) (const void *) &new_observation->token, token, @@ -772,7 +777,7 @@ find_or_create_connection_state(anjay_connection_ref_t ref) { || !((*conn_ptr)->observed_paths = AVS_SORTED_SET_NEW( anjay_observe_path_entry_t, _anjay_observe_path_entry_cmp))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); if (*conn_ptr) { AVS_SORTED_SET_DELETE(&(*conn_ptr)->observations); AVS_LIST_DELETE(conn_ptr); @@ -934,7 +939,7 @@ static int read_as_batch(anjay_unlocked_t *anjay, assert(out_batch && !*out_batch); anjay_batch_builder_t *builder = _anjay_batch_builder_new(); if (!builder) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } @@ -953,7 +958,7 @@ static int read_as_batch(anjay_unlocked_t *anjay, # endif // defined(ANJAY_WITH_LWM2M11) && // !defined(ANJAY_WITHOUT_COMPOSITE_OPERATIONS) if (!result && !(*out_batch = _anjay_batch_builder_compile(&builder))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); result = -1; } _anjay_batch_builder_cleanup(&builder); @@ -1076,6 +1081,24 @@ initial_response_details(anjay_unlocked_t *anjay, anjay, request, requires_hierarchical_format, lwm2m_version); } +static int multiple_batches_item_count(anjay_unlocked_t *anjay, + size_t values_count, + const anjay_batch_t *const *values, + size_t *out_count) { + size_t item_count = 0; + for (size_t i = 0; i < values_count; ++i) { + size_t batch_count; + if (_anjay_batch_outputable_item_count( + anjay, values[i], ANJAY_SSID_BOOTSTRAP, &batch_count)) { + return -1; + } else { + item_count += batch_count; + } + } + *out_count = item_count; + return 0; +} + static int send_initial_response(anjay_unlocked_t *anjay, const anjay_msg_details_t *details, const anjay_request_t *request, @@ -1097,10 +1120,15 @@ static int send_initial_response(anjay_unlocked_t *anjay, # endif // defined(ANJAY_WITH_LWM2M11) && // !defined(ANJAY_WITHOUT_COMPOSITE_OPERATIONS) + size_t item_count; anjay_unlocked_output_ctx_t *out_ctx = NULL; - int result = - _anjay_output_dynamic_construct(&out_ctx, notify_stream, &root_path, - details->format, request->action); + int result = _anjay_output_dynamic_construct( + &out_ctx, notify_stream, &root_path, details->format, + multiple_batches_item_count(anjay, values_count, values, + &item_count) + ? NULL + : &item_count, + request->action); for (size_t i = 0; !result && i < values_count; ++i) { // NOTE: Access Control permissions have been checked during the // read_as_batch() stage, so we're "spoofing" ANJAY_SSID_BOOTSTRAP @@ -1160,7 +1188,7 @@ static int read_observation_values(anjay_unlocked_t *anjay, if (paths->count && !(*out_batches = (anjay_batch_t **) avs_calloc( paths->count, sizeof(anjay_batch_t *)))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } @@ -1530,11 +1558,20 @@ initialize_serialization_state(anjay_observe_connection_entry_t *conn) { anjay_observation_value_t *value = conn->unsent; const anjay_uri_path_t root_path = get_response_path(value); + size_t item_count; if (!(conn->serialization_state.membuf_stream = avs_stream_membuf_create()) || _anjay_output_dynamic_construct( &conn->serialization_state.out_ctx, conn->serialization_state.membuf_stream, &root_path, - value->details.format, value->ref->action)) { + value->details.format, + multiple_batches_item_count( + _anjay_from_server(conn->conn_ref.server), + value->ref->paths_count, + cast_to_const_batch_array(value->values), + &item_count) + ? NULL + : &item_count, + value->ref->action)) { return -1; } conn->serialization_state.serialization_time = avs_time_real_now(); @@ -1720,7 +1757,7 @@ update_notification_value(anjay_observe_connection_entry_t *conn_state, if (observation->paths_count && !(batches = (anjay_batch_t **) avs_calloc( observation->paths_count, sizeof(anjay_batch_t *)))) { - anjay_log(ERROR, _("Out of memory")); + _anjay_log_oom(); return -1; } diff --git a/src/core/servers/anjay_activate.c b/src/core/servers/anjay_activate.c index bb09924b..097c8fea 100644 --- a/src/core/servers/anjay_activate.c +++ b/src/core/servers/anjay_activate.c @@ -527,7 +527,7 @@ _anjay_servers_create_inactive(anjay_unlocked_t *anjay, anjay_ssid_t ssid) { AVS_LIST(anjay_server_info_t) new_server = AVS_LIST_NEW_ELEMENT(anjay_server_info_t); if (!new_server) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } diff --git a/src/core/servers/anjay_connections.c b/src/core/servers/anjay_connections.c index 735d025f..4bf31466 100644 --- a/src/core/servers/anjay_connections.c +++ b/src/core/servers/anjay_connections.c @@ -87,7 +87,7 @@ static int read_security_info_ret_bytes_begin( } if (!(ctx->out_array = (avs_crypto_security_info_union_t *) avs_malloc( sizeof(*ctx->out_array) + length))) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } *ctx->out_array = (const avs_crypto_security_info_union_t) { diff --git a/src/core/servers/anjay_register.c b/src/core/servers/anjay_register.c index 07cbb7ab..fc4ef2b9 100644 --- a/src/core/servers/anjay_register.c +++ b/src/core/servers/anjay_register.c @@ -341,7 +341,7 @@ query_dm(anjay_unlocked_t *anjay, anjay_lwm2m_version_t version, char **out) { assert(!*out); avs_stream_t *stream = avs_stream_membuf_create(); if (!stream) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } int retval; @@ -512,7 +512,7 @@ static int get_endpoint_path(AVS_LIST(const anjay_string_t) *out_path, AVS_LIST(anjay_string_t) segment = (AVS_LIST(anjay_string_t)) AVS_LIST_NEW_BUFFER(attr_size + 1); if (!segment) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); goto fail; } diff --git a/src/core/servers/anjay_security_generic.c b/src/core/servers/anjay_security_generic.c index 00ac2cb0..d9bb3e04 100644 --- a/src/core/servers/anjay_security_generic.c +++ b/src/core/servers/anjay_security_generic.c @@ -78,18 +78,15 @@ static int get_security_mode(anjay_unlocked_t *anjay, } switch (mode) { - case ANJAY_SECURITY_RPK: - anjay_log(ERROR, _("unsupported security mode: ") "%s", - AVS_INT64_AS_STRING(mode)); - return -1; case ANJAY_SECURITY_NOSEC: case ANJAY_SECURITY_PSK: case ANJAY_SECURITY_CERTIFICATE: case ANJAY_SECURITY_EST: *out_mode = (anjay_security_mode_t) mode; return 0; + case ANJAY_SECURITY_RPK: default: - anjay_log(ERROR, _("invalid security mode: ") "%s", + anjay_log(ERROR, _("unsupported security mode: ") "%s", AVS_INT64_AS_STRING(mode)); return -1; } @@ -235,7 +232,7 @@ static avs_error_t init_cert_security(anjay_unlocked_t *anjay, avs_stream_t *server_pk_membuf = avs_stream_membuf_create(); if (!server_pk_membuf) { - anjay_log(ERROR, _("out of memory")); + _anjay_log_oom(); return avs_errno(AVS_ENOMEM); } avs_net_socket_dane_tlsa_record_t dane_tlsa_record = { @@ -360,8 +357,6 @@ static avs_error_t init_security(anjay_unlocked_t *anjay, security_mode, cache); case ANJAY_SECURITY_RPK: default: - anjay_log(ERROR, _("unsupported security mode: ") "%d", - (int) security_mode); return avs_errno(AVS_EINVAL); } } diff --git a/src/core/servers/anjay_servers_internal.c b/src/core/servers/anjay_servers_internal.c index 0f718938..540ae342 100644 --- a/src/core/servers/anjay_servers_internal.c +++ b/src/core/servers/anjay_servers_internal.c @@ -124,7 +124,7 @@ static int add_socket_onto_list(AVS_LIST(anjay_socket_entry_t) *tail_ptr, assert(!*tail_ptr); AVS_LIST_INSERT_NEW(anjay_socket_entry_t, tail_ptr); if (!*tail_ptr) { - anjay_log(ERROR, _("Out of memory while building socket list")); + _anjay_log_oom(); return -1; } (*tail_ptr)->socket = socket; diff --git a/src/modules/access_control/anjay_access_control_handlers.c b/src/modules/access_control/anjay_access_control_handlers.c index 7d86b82a..87266116 100644 --- a/src/modules/access_control/anjay_access_control_handlers.c +++ b/src/modules/access_control/anjay_access_control_handlers.c @@ -82,7 +82,7 @@ static int ac_instance_create(anjay_unlocked_t *anjay, AVS_LIST(access_control_instance_t) new_instance = AVS_LIST_NEW_ELEMENT(access_control_instance_t); if (!new_instance) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); return ANJAY_ERR_INTERNAL; } *new_instance = (access_control_instance_t) { @@ -349,7 +349,7 @@ static int ac_transaction_begin(anjay_unlocked_t *anjay, obj_ptr_t obj_ptr) { access_control_t *ac = _anjay_access_control_from_obj_ptr(obj_ptr); assert(!ac->in_transaction); if (_anjay_access_control_clone_state(&ac->saved_state, &ac->current)) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); return ANJAY_ERR_INTERNAL; } ac->in_transaction = true; @@ -368,7 +368,7 @@ static int add_ssid(AVS_SORTED_SET(anjay_ssid_t) ssids_list, AVS_SORTED_SET_FIND(ssids_list, &ssid); if (!elem) { if (!(elem = AVS_SORTED_SET_ELEM_NEW(anjay_ssid_t))) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } *elem = ssid; @@ -401,7 +401,7 @@ static int ac_transaction_validate(anjay_unlocked_t *anjay, obj_ptr_t obj_ptr) { AVS_SORTED_SET(anjay_ssid_t) ssids_used = NULL; if (access_control->needs_validation) { if (!(ssids_used = AVS_SORTED_SET_NEW(anjay_ssid_t, anjay_ssid_cmp))) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); goto finish; } access_control_instance_t *inst; diff --git a/src/modules/access_control/anjay_access_control_persistence.c b/src/modules/access_control/anjay_access_control_persistence.c index 65c0d3d9..3657f624 100644 --- a/src/modules/access_control/anjay_access_control_persistence.c +++ b/src/modules/access_control/anjay_access_control_persistence.c @@ -119,7 +119,7 @@ restore_instances(anjay_unlocked_t *anjay, AVS_LIST(access_control_instance_t) entry = AVS_LIST_NEW_ELEMENT(access_control_instance_t); if (!entry) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); return avs_errno(AVS_ENOMEM); } *entry = instance; diff --git a/src/modules/access_control/anjay_mod_access_control.c b/src/modules/access_control/anjay_mod_access_control.c index 1291a182..c8f90659 100644 --- a/src/modules/access_control/anjay_mod_access_control.c +++ b/src/modules/access_control/anjay_mod_access_control.c @@ -252,7 +252,7 @@ static int set_acl_in_instance(anjay_unlocked_t *anjay, AVS_LIST(acl_entry_t) new_entry = AVS_LIST_NEW_ELEMENT(acl_entry_t); if (!new_entry) { - ac_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } diff --git a/src/modules/advanced_fw_update/anjay_advanced_fw_update.c b/src/modules/advanced_fw_update/anjay_advanced_fw_update.c index 4f18199c..2515ae89 100644 --- a/src/modules/advanced_fw_update/anjay_advanced_fw_update.c +++ b/src/modules/advanced_fw_update/anjay_advanced_fw_update.c @@ -177,7 +177,7 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, anjay_send_batch_builder_t *batch_builder = anjay_send_batch_builder_new(); if (!batch_builder) { - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); return; } if (_anjay_send_batch_data_add_current_multiple_unlocked( @@ -190,7 +190,7 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, anjay_send_batch_builder_compile(&batch_builder); if (!batch) { anjay_send_batch_builder_cleanup(&batch_builder); - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); return; } send_batch_to_all_servers(anjay, batch); @@ -985,7 +985,7 @@ static int enqueue_download(anjay_unlocked_t *anjay, return 0; cleanup: - fw_log(ERROR, _("Out of memory")); + _anjay_log_oom(); if (new_download) { avs_free((void *) (intptr_t) new_download->url); AVS_LIST_DELETE(&new_download); @@ -1455,7 +1455,7 @@ static int handle_fw_execute_args(advanced_fw_repr_t *fw, avs_stream_t *supplemental_iid_cache_membuf = avs_stream_membuf_create(); if (!supplemental_iid_cache_membuf) { - fw_log(ERROR, _("Out of memory")); + _anjay_log_oom(); return ANJAY_ERR_INTERNAL; } @@ -1520,7 +1520,7 @@ static int handle_fw_execute_args(advanced_fw_repr_t *fw, if (avs_is_err(avs_stream_write(supplemental_iid_cache_membuf, &supplemental_iid, sizeof(supplemental_iid)))) { - fw_log(ERROR, _("Out of memory")); + _anjay_log_oom(); result = ANJAY_ERR_INTERNAL; goto finish; } @@ -1690,7 +1690,7 @@ static AVS_LIST(advanced_fw_instance_t) initialize_fw_instance( AVS_LIST_NEW_ELEMENT(advanced_fw_instance_t); if (!inst) { - fw_log(ERROR, _("Out of memory")); + _anjay_log_oom(); return NULL; } @@ -1793,7 +1793,7 @@ int anjay_advanced_fw_update_install( AVS_LIST(advanced_fw_repr_t) repr = AVS_LIST_NEW_ELEMENT(advanced_fw_repr_t); if (!repr) { - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); } else { repr->def = &FIRMWARE_UPDATE; repr->current_download.iid = ANJAY_ID_INVALID; @@ -2074,7 +2074,7 @@ static int copy_target_iid_list(anjay_iid_t **out_instances, } if (target_iids_count && !new_ptr) { - fw_log(ERROR, _("Out of memory")); + _anjay_log_oom(); return -1; } diff --git a/src/modules/fw_update/anjay_fw_update.c b/src/modules/fw_update/anjay_fw_update.c index e34c0e3f..967e712d 100644 --- a/src/modules/fw_update/anjay_fw_update.c +++ b/src/modules/fw_update/anjay_fw_update.c @@ -149,7 +149,7 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, anjay_send_batch_builder_t *batch_builder = anjay_send_batch_builder_new(); if (!batch_builder) { - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); return; } @@ -164,7 +164,7 @@ static void perform_lwm2m_send(anjay_unlocked_t *anjay, anjay_send_batch_builder_compile(&batch_builder); if (!batch) { anjay_send_batch_builder_cleanup(&batch_builder); - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); return; } @@ -1265,7 +1265,7 @@ int anjay_fw_update_install( ANJAY_MUTEX_LOCK(anjay, anjay_locked); AVS_LIST(fw_repr_t) repr = AVS_LIST_NEW_ELEMENT(fw_repr_t); if (!repr) { - fw_log(ERROR, _("out of memory")); + _anjay_log_oom(); } else { repr->def = &FIRMWARE_UPDATE; _anjay_dm_installed_object_init_unlocked(&repr->def_ptr, &repr->def); diff --git a/src/modules/ipso/anjay_ipso_3d_sensor.c b/src/modules/ipso/anjay_ipso_3d_sensor.c index b80ff17f..813dde59 100644 --- a/src/modules/ipso/anjay_ipso_3d_sensor.c +++ b/src/modules/ipso/anjay_ipso_3d_sensor.c @@ -278,7 +278,7 @@ int anjay_ipso_3d_sensor_install(anjay_t *anjay_locked, sizeof(anjay_ipso_3d_sensor_t) + num_instances * sizeof(anjay_ipso_3d_sensor_instance_t)); if (!obj) { - _anjay_log(ipso, ERROR, _("Out of memory")); + _anjay_log_oom(); err = -1; goto finish; } diff --git a/src/modules/ipso/anjay_ipso_basic_sensor.c b/src/modules/ipso/anjay_ipso_basic_sensor.c index 47feb382..b5f52122 100644 --- a/src/modules/ipso/anjay_ipso_basic_sensor.c +++ b/src/modules/ipso/anjay_ipso_basic_sensor.c @@ -327,7 +327,7 @@ int anjay_ipso_basic_sensor_install(anjay_t *anjay_locked, + num_instances * sizeof(anjay_ipso_basic_sensor_instance_t)); if (!obj) { - _anjay_log(ipso, ERROR, _("Out of memory")); + _anjay_log_oom(); err = -1; goto finish; } diff --git a/src/modules/ipso/anjay_ipso_button.c b/src/modules/ipso/anjay_ipso_button.c index 3694f45a..0afe46bf 100644 --- a/src/modules/ipso/anjay_ipso_button.c +++ b/src/modules/ipso/anjay_ipso_button.c @@ -250,7 +250,7 @@ int anjay_ipso_button_install(anjay_t *anjay_locked, size_t num_instances) { sizeof(anjay_ipso_button_t) + num_instances * sizeof(anjay_ipso_button_instance_t)); if (!obj) { - _anjay_log(ipso, ERROR, _("Out of memory")); + _anjay_log_oom(); err = -1; goto finish; } diff --git a/src/modules/security/anjay_mod_security.c b/src/modules/security/anjay_mod_security.c index 07a1e6b7..1ad59d91 100644 --- a/src/modules/security/anjay_mod_security.c +++ b/src/modules/security/anjay_mod_security.c @@ -116,7 +116,7 @@ static int add_instance(sec_repr_t *repr, AVS_LIST(sec_instance_t) new_instance = AVS_LIST_NEW_ELEMENT(sec_instance_t); if (!new_instance) { - security_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } init_instance(new_instance, *inout_iid); @@ -237,7 +237,7 @@ static int add_instance(sec_repr_t *repr, if (instance->server_name_indication && !(new_instance->server_name_indication = avs_strdup(instance->server_name_indication))) { - security_log(ERROR, _("Could not copy SNI: out of memory")); + _anjay_log_oom(); goto error; } if (instance->certificate_usage) { @@ -254,8 +254,7 @@ static int add_instance(sec_repr_t *repr, AVS_LIST(sec_cipher_instance_t) cipher_instance = AVS_LIST_NEW_ELEMENT(sec_cipher_instance_t); if (!cipher_instance) { - security_log(ERROR, - _("Could not copy ciphersuites: out of memory")); + _anjay_log_oom(); goto error; } cipher_instance->riid = (anjay_riid_t) i; @@ -825,7 +824,7 @@ bool anjay_security_object_is_modified(anjay_t *anjay_locked) { static sec_repr_t *security_install_unlocked(anjay_unlocked_t *anjay) { AVS_LIST(sec_repr_t) repr = AVS_LIST_NEW_ELEMENT(sec_repr_t); if (!repr) { - security_log(ERROR, _("out of memory")); + _anjay_log_oom(); return NULL; } int result = -1; diff --git a/src/modules/server/anjay_mod_server.c b/src/modules/server/anjay_mod_server.c index 185f2bdb..061aed3a 100644 --- a/src/modules/server/anjay_mod_server.c +++ b/src/modules/server/anjay_mod_server.c @@ -176,7 +176,7 @@ static int add_instance(server_repr_t *repr, AVS_LIST(server_instance_t) new_instance = AVS_LIST_NEW_ELEMENT(server_instance_t); if (!new_instance) { - server_log(ERROR, _("out of memory")); + _anjay_log_oom(); return -1; } if (instance->binding) { @@ -748,7 +748,7 @@ int anjay_server_object_install(anjay_t *anjay_locked) { ANJAY_MUTEX_LOCK(anjay, anjay_locked); AVS_LIST(server_repr_t) repr = AVS_LIST_NEW_ELEMENT(server_repr_t); if (!repr) { - server_log(ERROR, _("out of memory")); + _anjay_log_oom(); } else { repr->def = &SERVER; _anjay_dm_installed_object_init_unlocked(&repr->def_ptr, &repr->def); diff --git a/tests/core/io/cbor/cbor_encoder.c b/tests/core/io/cbor/cbor_encoder.c index 36e6cee2..9b11fb8c 100644 --- a/tests/core/io/cbor/cbor_encoder.c +++ b/tests/core/io/cbor/cbor_encoder.c @@ -396,7 +396,25 @@ AVS_UNIT_TEST(cbor_encoder, definite_array) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_known_length_definite_array_begin(encoder, 3)); + AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); + AVS_UNIT_ASSERT_SUCCESS(cbor_encode_string(encoder, "cwiercz")); + AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 200)); + AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); + AVS_UNIT_ASSERT_EQUAL(nested_context_top(encoder)->size, 1); + AVS_UNIT_ASSERT_SUCCESS(cbor_encoder_delete(&encoder)); + VERIFY_BYTES(env, "\x83\x01\x67\x63\x77\x69\x65\x72\x63\x7A\x18\xC8"); + + avs_free(env.buf); +} + +// [1, "cwiercz", 200] +AVS_UNIT_TEST(cbor_encoder, cached_definite_array) { + cbor_test_env_t env; + cbor_test_setup(&env, 32); + cbor_encoder_t *encoder = env.encoder; + + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_string(encoder, "cwiercz")); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 200)); @@ -414,7 +432,23 @@ AVS_UNIT_TEST(cbor_encoder, empty_definite_array) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_known_length_definite_array_begin(encoder, 0)); + AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); + AVS_UNIT_ASSERT_EQUAL(nested_context_top(encoder)->size, 1); + AVS_UNIT_ASSERT_SUCCESS(cbor_encoder_delete(&encoder)); + + VERIFY_BYTES(env, "\x80"); + + avs_free(env.buf); +} + +// [] +AVS_UNIT_TEST(cbor_encoder, cached_empty_definite_array) { + cbor_test_env_t env; + cbor_test_setup(&env, 32); + cbor_encoder_t *encoder = env.encoder; + + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); AVS_UNIT_ASSERT_EQUAL(nested_context_top(encoder)->size, 1); AVS_UNIT_ASSERT_SUCCESS(cbor_encoder_delete(&encoder)); @@ -430,9 +464,9 @@ AVS_UNIT_TEST(cbor_encoder, nested_definite_arrays1) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_known_length_definite_array_begin(encoder, 2)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 2)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); @@ -450,10 +484,10 @@ AVS_UNIT_TEST(cbor_encoder, nested_definite_arrays2) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 2)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_known_length_definite_array_begin(encoder, 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 4)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 5)); @@ -475,7 +509,7 @@ AVS_UNIT_TEST(cbor_encoder, map_with_array_with_bytes) { AVS_UNIT_ASSERT_SUCCESS(cbor_definite_map_begin(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_string(encoder, "array")); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_known_length_definite_array_begin(encoder, 2)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_begin(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_append(encoder, "\x00", 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_end(encoder)); @@ -498,8 +532,8 @@ AVS_UNIT_TEST(cbor_encoder, empty_nested_arrays) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); AVS_UNIT_ASSERT_EQUAL(nested_context_top(encoder)->size, 1); @@ -516,11 +550,11 @@ AVS_UNIT_TEST(cbor_encoder, double_nested_arrays) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 2)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); @@ -539,16 +573,16 @@ AVS_UNIT_TEST(cbor_encoder, three_nested_arrays) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_uint(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 2)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_uint(encoder, 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 4)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_uint(encoder, 5)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 6)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_end(encoder)); @@ -567,7 +601,7 @@ AVS_UNIT_TEST(cbor_encoder, array_with_one_map) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_map_begin(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_string(encoder, "A")); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); @@ -587,7 +621,7 @@ AVS_UNIT_TEST(cbor_encoder, array_with_two_maps) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_definite_map_begin(encoder, 1)); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_string(encoder, "A")); AVS_UNIT_ASSERT_SUCCESS(cbor_encode_int(encoder, 1)); @@ -611,7 +645,7 @@ AVS_UNIT_TEST(cbor_encoder, array_with_bytes) { cbor_test_setup(&env, 32); cbor_encoder_t *encoder = env.encoder; - AVS_UNIT_ASSERT_SUCCESS(cbor_definite_array_begin(encoder)); + AVS_UNIT_ASSERT_SUCCESS(cbor_unknown_length_definite_array_begin(encoder)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_begin(encoder, 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_append(encoder, "\xAA\xBB\xCC", 3)); AVS_UNIT_ASSERT_SUCCESS(cbor_bytes_end(encoder)); diff --git a/tests/core/io/dm_batch.c b/tests/core/io/dm_batch.c index d48cf829..345eaade 100644 --- a/tests/core/io/dm_batch.c +++ b/tests/core/io/dm_batch.c @@ -470,7 +470,7 @@ AVS_UNIT_TEST(dm_batch, serialize_empty) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -513,7 +513,7 @@ AVS_UNIT_TEST(dm_batch, serialize_bytes) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -551,7 +551,7 @@ AVS_UNIT_TEST(dm_batch, serialize_one_resource) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -591,7 +591,7 @@ AVS_UNIT_TEST(dm_batch, serialize_one_resource_with_absolute_timestamp) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -634,7 +634,7 @@ AVS_UNIT_TEST(dm_batch, serialize_two_resources) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -683,7 +683,7 @@ AVS_UNIT_TEST(dm_batch, serialize_two_resources_with_relative_timestamp) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -725,7 +725,7 @@ AVS_UNIT_TEST(dm_batch, serialize_resource_instance) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -766,7 +766,7 @@ AVS_UNIT_TEST(dm_batch, absolute_timestamp_higher_than_serialization_time) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -808,7 +808,7 @@ AVS_UNIT_TEST(dm_batch, relative_timestamp_higher_than_serialization_time) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -849,7 +849,7 @@ AVS_UNIT_TEST(dm_batch, relative_timestamp_absolute_serialization_time) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( @@ -897,7 +897,7 @@ AVS_UNIT_TEST(dm_batch, negative_timestamp) { anjay_unlocked_output_ctx_t *out_ctx = _anjay_output_senml_like_create((avs_stream_t *) &stream, &MAKE_ROOT_PATH(), - AVS_COAP_FORMAT_SENML_JSON); + AVS_COAP_FORMAT_SENML_JSON, NULL); AVS_UNIT_ASSERT_NOT_NULL(out_ctx); ANJAY_MUTEX_LOCK(anjay_unlocked, anjay); AVS_UNIT_ASSERT_SUCCESS( diff --git a/tests/core/io/dynamic.c b/tests/core/io/dynamic.c index a49f7eb2..7e29990d 100644 --- a/tests/core/io/dynamic.c +++ b/tests/core/io/dynamic.c @@ -33,7 +33,7 @@ avs_stream_outbuf_set_buffer(&outbuf, buf, sizeof(buf)); \ anjay_unlocked_output_ctx_t *out = NULL; \ ASSERT_OK(_anjay_output_dynamic_construct(&out, (avs_stream_t *) &outbuf, \ - (Uri), (Format), \ + (Uri), (Format), NULL, \ ANJAY_ACTION_READ)); #define PATH_HIERARCHICAL true diff --git a/tests/core/io/senml_cbor_encoder.c b/tests/core/io/senml_cbor_encoder.c index 98478d78..4f57f2d6 100644 --- a/tests/core/io/senml_cbor_encoder.c +++ b/tests/core/io/senml_cbor_encoder.c @@ -44,7 +44,8 @@ static void cbor_test_setup(cbor_test_env_t *env, size_t buf_size) { env->buf = avs_malloc(buf_size); AVS_UNIT_ASSERT_NOT_NULL(env->buf); avs_stream_outbuf_set_buffer(&env->outbuf, env->buf, buf_size); - env->encoder = _anjay_senml_cbor_encoder_new((avs_stream_t *) &env->outbuf); + env->encoder = + _anjay_senml_cbor_encoder_new((avs_stream_t *) &env->outbuf, NULL); AVS_UNIT_ASSERT_NOT_NULL(env->encoder); } diff --git a/tests/core/observe/observe.c b/tests/core/observe/observe.c index 802c3d7f..b988b3d2 100644 --- a/tests/core/observe/observe.c +++ b/tests/core/observe/observe.c @@ -114,7 +114,7 @@ static void assert_observe(anjay_t *anjay_locked, anjay_unlocked_output_ctx_t *out_ctx = NULL; AVS_UNIT_ASSERT_SUCCESS(_anjay_output_dynamic_construct( &out_ctx, (avs_stream_t *) &out_buf_stream, uri, details->format, - ANJAY_ACTION_READ)); + NULL, ANJAY_ACTION_READ)); AVS_UNIT_ASSERT_SUCCESS( _anjay_batch_data_output(anjay, observation->last_sent->values[0], ANJAY_SSID_BOOTSTRAP, out_ctx)); diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt index cbe54c51..6f16b2b0 100644 --- a/tests/fuzz/CMakeLists.txt +++ b/tests/fuzz/CMakeLists.txt @@ -61,6 +61,7 @@ foreach(FUZZ_TEST_SOURCE ${FUZZ_TEST_SOURCES}) add_fuzz_target(${FUZZ_TEST_NAME} "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${FUZZ_TEST_NAME}_fuzz_test") endforeach() +set(AFL_FUZZ_MEMORY_LIMIT_MEGS 32) set(AFL_FUZZ_TIMEOUT_MS 1000) list(LENGTH FUZZ_TEST_NAMES FUZZ_TEST_COUNT) @@ -78,6 +79,7 @@ foreach(i RANGE ${FUZZ_TEST_MAX}) COMMAND "${AFL_FUZZ_EXECUTABLE}" -i "${FUZZ_TEST_CASE_DIR}" -o "${FUZZ_TEST_FINDINGS_DIR}" -t ${AFL_FUZZ_TIMEOUT_MS} + -m ${AFL_FUZZ_MEMORY_LIMIT_MEGS} "${${FUZZ_TEST_ARG_LIST_NAME}}" WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DEPENDS ${FUZZ_TEST_NAME}_fuzz_test)