diff --git a/.azure/templates/build-test.yml b/.azure/templates/build-test.yml index 0d767796ff..c6a4f17765 100644 --- a/.azure/templates/build-test.yml +++ b/.azure/templates/build-test.yml @@ -19,6 +19,13 @@ steps: inputs: versionSpec: '3.8' name: install_python + - bash: | + # Asan in llvm 14 provided in ubuntu 22.04 is incompatible with + # high-entropy ASLR in much newer kernels that GitHub runners are + # using leading to random crashes: https://reviews.llvm.org/D148280 + sudo sysctl vm.mmap_rnd_bits=28 + condition: eq(variables['Agent.OS'], 'Linux') + name: fix_kernel_mmap_rnd_bits # Set defaults from steps to share them among pipelines - bash: | [[ -n "${ARCH}" ]] || \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c02059129..fa04d62b6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,10 @@ elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") if(${WERROR}) add_compile_options(-Werror) add_link_options(-Werror) + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0 AND CMAKE_C_COMPILER_VERSION VERSION_LESS 13.2) + add_compile_options(-Wno-error=stringop-overflow -Wno-error=array-bounds) + add_link_options(-Wno-error=stringop-overflow -Wno-error=array-bounds) + endif() endif() if("${CMAKE_GENERATOR}" STREQUAL "Ninja") add_compile_options(-fdiagnostics-color=always) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f2b46f94ac..88e76ab3d5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -40,19 +40,23 @@ jobs: build_type: Release sanitizer: undefined cc: gcc-10 - 'Ubuntu 22.04 LTS with GCC 10 (Debug, x86_64, Iceoryx)': + 'Ubuntu 22.04 LTS with GCC 13 (Debug, x86_64, Iceoryx)': image: ubuntu-22.04 - #analyzer: on # disabled for now because of warnings - sanitizer: address,undefined + # No address sanitizer because of this in test run: + # Shadow memory range interleaves with an existing memory mapping. + # ASan cannot proceed correctly. ABORTING. + # ASan shadow was supposed to be located in the [0x00007fff7000-0x10007fff7fff] + # range. + sanitizer: undefined iceoryx: on - cc: gcc-10 + cc: gcc-13 coverage: on - 'Ubuntu 22.04 LTS with GCC 10 (Release, x86_64)': + 'Ubuntu 22.04 LTS with GCC 13 (Release, x86_64)': image: ubuntu-22.04 build_type: Release sanitizer: undefined - cc: gcc-10 - 'Ubuntu 22.04 LTS with GCC 10 (Debug, x86_64, security only)': + cc: gcc-13 + 'Ubuntu 22.04 LTS with GCC 12 (Debug, x86_64, security only)': image: ubuntu-22.04 sanitizer: address,undefined ssl: off @@ -61,72 +65,65 @@ jobs: type_discovery: off topic_discovery: off idlc_xtests: off # temporary disabled because of passing -t option to idlc in this test for recursive types - cc: gcc-10 - 'Ubuntu 22.04 LTS with GCC 10 (Debug, x86_64, no tests)': + cc: gcc-12 + 'Ubuntu 22.04 LTS with GCC 12 (Debug, x86_64, no tests)': image: ubuntu-22.04 - cc: gcc-10 + cc: gcc-12 testing: off idlc_xtests: off - 'Ubuntu 22.04 LTS with Clang 13 (Debug, x86_64)': + 'Ubuntu 22.04 LTS with Clang 15 (Debug, x86_64)': image: ubuntu-22.04 analyzer: on sanitizer: address,undefined - cc: clang-13 - 'Ubuntu 22.04 LTS with Clang 13 (Debug, x86_64, no security)': + cc: clang-15 + 'Ubuntu 22.04 LTS with Clang 15 (Debug, x86_64, no security)': image: ubuntu-22.04 sanitizer: address,undefined security: off - cc: clang-13 - 'Ubuntu 22.04 LTS with Clang 13 (Release, x86_64, no topic discovery)': + cc: clang-15 + 'Ubuntu 22.04 LTS with Clang 15 (Release, x86_64, no topic discovery)': image: ubuntu-22.04 build_type: Release sanitizer: undefined topic_discovery: off idlc_xtests: off # temporary disabled because of passing -t option to idlc in this test for recursive types - cc: clang-13 - 'macOS 11 with Clang 12 (Debug, x86_64)': - image: macOS-11 + cc: clang-15 + 'macOS 13 with Clang 15 (Debug, x86_64)': + image: macos-13 sanitizer: address,undefined deadline_update_skip: on cc: clang - 'macOS 11 with Clang 12 (Release, x86_64)': - image: macOS-11 - build_type: Release - sanitizer: undefined - deadline_update_skip: on - cc: clang - 'macOS 11 with Clang 13 (Release, x86_64)': - image: macOS-11 + 'macOS 13 with Clang 15 (Release, x86_64)': + image: macos-13 build_type: Release sanitizer: undefined deadline_update_skip: on cc: clang coverage: on - 'macOS 12 with gcc 12 (Debug, analyzer, x86_64)': - image: macOS-12 - sanitizer: undefined + 'macOS 13 with gcc 13 (Debug, analyzer, x86_64)': + image: macos-13 deadline_update_skip: on - cc: gcc-12 + cc: gcc-13 analyzer: on # 32-bit Windows: without SSL/security because Chocolateley only provides 64-bit OpenSSL - 'Windows 2019 with Visual Studio 2019 (Visual Studio 2017, Debug, x86, no security)': + 'Windows 2022 with Visual Studio 2022 (Debug, x86, no security)': arch: x86 - image: windows-2019 + image: windows-2022 ssl: off security: off idlc_xtests: off - generator: 'Visual Studio 16 2019' + generator: 'Visual Studio 17 2022' toolset: v141 - 'Windows 2019 with Visual Studio 2019 (Debug, x86_64)': - image: windows-2019 + 'Windows 2022 with Visual Studio 2022 (Debug, x86_64)': + image: windows-2022 idlc_xtests: off - generator: 'Visual Studio 16 2019' - 'Windows 2019 with Visual Studio 2019 (Release, x86_64, no tests)': - image: windows-2019 + generator: 'Visual Studio 17 2022' + 'Windows 2022 with Visual Studio 2022 (Release, x86_64, no tests)': + image: windows-2022 build_type: Release testing: off idlc_xtests: off - generator: 'Visual Studio 16 2019' + generator: 'Visual Studio 17 2022' 'Windows 2019 with Visual Studio 2019 (RelWithDebInfo, x86_64)': image: windows-2019 build_type: RelWithDebInfo diff --git a/examples/dynsub/dynsub.c b/examples/dynsub/dynsub.c index 8de1b843ea..a224209c52 100644 --- a/examples/dynsub/dynsub.c +++ b/examples/dynsub/dynsub.c @@ -121,6 +121,7 @@ static dds_return_t get_topic_and_typeobj (const char *topic_name, dds_duration_ { // not sure whether this is at all possible info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) *xtypeobj }, .typeobj = &(*xtypeobj)->_u.complete, .release = *xtypeobj, .align = align, .size = size }; type_cache_add (info); } diff --git a/examples/dynsub/type_cache.c b/examples/dynsub/type_cache.c index da845709d0..d755eefe82 100644 --- a/examples/dynsub/type_cache.c +++ b/examples/dynsub/type_cache.c @@ -252,6 +252,7 @@ static void build_typecache_ti (const DDS_XTypes_TypeIdentifier *typeid, size_t const DDS_XTypes_CompleteTypeObject *tobj = get_complete_typeobj_for_hashid (typeid->_u.equivalence_hash); build_typecache_to (tobj, align, size); info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeid }, .typeobj = tobj, .release = NULL, .align = *align, .size = *size }; type_cache_add (info); } @@ -289,6 +290,7 @@ void build_typecache_to (const DDS_XTypes_CompleteTypeObject *typeobj, size_t *a *align = sizeof (int); *size = sizeof (int); info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeobj }, .typeobj = typeobj, .release = NULL, .align = *align, .size = *size }; ddsrt_hh_add (typecache, info); } @@ -310,6 +312,7 @@ void build_typecache_to (const DDS_XTypes_CompleteTypeObject *typeobj, size_t *a else *align = *size = 1; info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeobj }, .typeobj = typeobj, .release = NULL, .align = *align, .size = *size }; ddsrt_hh_add (typecache, info); } @@ -327,6 +330,7 @@ void build_typecache_to (const DDS_XTypes_CompleteTypeObject *typeobj, size_t *a *align = a; *size = s; info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeobj }, .typeobj = typeobj, .release = NULL, .align = *align, .size = *size }; ddsrt_hh_add (typecache, info); } @@ -354,6 +358,7 @@ void build_typecache_to (const DDS_XTypes_CompleteTypeObject *typeobj, size_t *a if (*size % *align) *size += *align - (*size % *align); info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeobj }, .typeobj = typeobj, .release = NULL, .align = *align, .size = *size }; ddsrt_hh_add (typecache, info); } @@ -391,6 +396,7 @@ void build_typecache_to (const DDS_XTypes_CompleteTypeObject *typeobj, size_t *a if (*size % *align) *size += *align - (*size % *align); info = malloc (sizeof (*info)); + assert (info); *info = (struct typeinfo){ .key = { .key = (uintptr_t) typeobj }, .typeobj = typeobj, .release = NULL, .align = *align, .size = *size }; ddsrt_hh_add (typecache, info); } @@ -468,6 +474,7 @@ static bool load_deps_ti (dds_entity_t participant, const DDS_XTypes_TypeIdentif return load_deps_failed (); DDS_XTypes_TypeObject * const xtypeobj = (DDS_XTypes_TypeObject *) typeobj; info = malloc (sizeof (*info)); + assert (info); memcpy (info->id, typeid->_u.equivalence_hash, sizeof (info->id)); info->typeobj = xtypeobj; info->lineno = 0; diff --git a/examples/roundtrip/ping.c b/examples/roundtrip/ping.c index 1c58801247..244c4470df 100644 --- a/examples/roundtrip/ping.c +++ b/examples/roundtrip/ping.c @@ -53,8 +53,7 @@ static void exampleDeleteTimeStats (ExampleTimeStats *stats) free (stats->values); } -static ExampleTimeStats *exampleAddTimingToTimeStats - (ExampleTimeStats *stats, dds_time_t timing) +static void exampleAddTimingToTimeStats (ExampleTimeStats *stats, dds_time_t timing) { if (stats->valuesSize > stats->valuesMax) { @@ -70,8 +69,6 @@ static ExampleTimeStats *exampleAddTimingToTimeStats stats->min = (stats->count == 0 || timing < stats->min) ? timing : stats->min; stats->max = (stats->count == 0 || timing > stats->max) ? timing : stats->max; stats->count++; - - return stats; } static int exampleCompareul (const void* a, const void* b) @@ -166,16 +163,16 @@ static void data_available(dds_entity_t rd, void *arg) /* Update stats */ difference = (postWriteTime - preWriteTime)/DDS_NSECS_IN_USEC; - writeAccess = *exampleAddTimingToTimeStats (&writeAccess, difference); - writeAccessOverall = *exampleAddTimingToTimeStats (&writeAccessOverall, difference); + exampleAddTimingToTimeStats (&writeAccess, difference); + exampleAddTimingToTimeStats (&writeAccessOverall, difference); difference = (postTakeTime - preTakeTime)/DDS_NSECS_IN_USEC; - readAccess = *exampleAddTimingToTimeStats (&readAccess, difference); - readAccessOverall = *exampleAddTimingToTimeStats (&readAccessOverall, difference); + exampleAddTimingToTimeStats (&readAccess, difference); + exampleAddTimingToTimeStats (&readAccessOverall, difference); difference = (postTakeTime - info[0].source_timestamp)/DDS_NSECS_IN_USEC; - roundTrip = *exampleAddTimingToTimeStats (&roundTrip, difference); - roundTripOverall = *exampleAddTimingToTimeStats (&roundTripOverall, difference); + exampleAddTimingToTimeStats (&roundTrip, difference); + exampleAddTimingToTimeStats (&roundTripOverall, difference); if (!warmUp) { /* Print stats each second */ diff --git a/src/core/ddsc/src/dds_instance.c b/src/core/ddsc/src/dds_instance.c index c2143d79b9..cff08e07a2 100644 --- a/src/core/ddsc/src/dds_instance.c +++ b/src/core/ddsc/src/dds_instance.c @@ -159,9 +159,13 @@ dds_return_t dds_unregister_instance_ih_ts (dds_entity_t writer, dds_instance_ha { struct ddsi_sertype *tp = wr->m_topic->m_stype; void *sample = ddsi_sertype_alloc_sample (tp); - ddsi_serdata_untyped_to_sample (tp, tk->m_sample, sample, NULL, NULL); - ddsi_tkmap_instance_unref (wr->m_entity.m_domain->gv.m_tkmap, tk); - ret = dds_write_impl (wr, sample, timestamp, action); + if (!ddsi_serdata_untyped_to_sample (tp, tk->m_sample, sample, NULL, NULL)) + ret = DDS_RETCODE_ERROR; + else + { + ddsi_tkmap_instance_unref (wr->m_entity.m_domain->gv.m_tkmap, tk); + ret = dds_write_impl (wr, sample, timestamp, action); + } ddsi_sertype_free_sample (tp, sample, DDS_FREE_ALL); } ddsi_thread_state_asleep (thrst); @@ -239,9 +243,13 @@ dds_return_t dds_dispose_ih_ts (dds_entity_t writer, dds_instance_handle_t handl { const struct ddsi_sertype *tp = wr->m_wr->type; void *sample = ddsi_sertype_alloc_sample (tp); - ddsi_serdata_untyped_to_sample (tp, tk->m_sample, sample, NULL, NULL); - ddsi_tkmap_instance_unref (wr->m_entity.m_domain->gv.m_tkmap, tk); - ret = dds_dispose_impl (wr, sample, handle, timestamp); + if (!ddsi_serdata_untyped_to_sample (tp, tk->m_sample, sample, NULL, NULL)) + ret = DDS_RETCODE_ERROR; + else + { + ddsi_tkmap_instance_unref (wr->m_entity.m_domain->gv.m_tkmap, tk); + ret = dds_dispose_impl (wr, sample, handle, timestamp); + } ddsi_sertype_free_sample (tp, sample, DDS_FREE_ALL); } ddsi_thread_state_asleep (thrst); @@ -327,9 +335,13 @@ dds_return_t dds_instance_get_key (dds_entity_t entity, dds_instance_handle_t ih /* Use sertype from topic, as the zero_sample and untyped_to_sample functions are identical for the derived sertype that is stored in the endpoint. */ ddsi_sertype_zero_sample (topic->m_stype, data); - ddsi_serdata_untyped_to_sample (topic->m_stype, tk->m_sample, data, NULL, NULL); - ddsi_tkmap_instance_unref (e->m_domain->gv.m_tkmap, tk); - ret = DDS_RETCODE_OK; + if (!ddsi_serdata_untyped_to_sample (topic->m_stype, tk->m_sample, data, NULL, NULL)) + ret = DDS_RETCODE_ERROR; + else + { + ddsi_tkmap_instance_unref (e->m_domain->gv.m_tkmap, tk); + ret = DDS_RETCODE_OK; + } } ddsi_thread_state_asleep (thrst); dds_entity_unlock (e); diff --git a/src/core/ddsc/src/dds_rhc_default.c b/src/core/ddsc/src/dds_rhc_default.c index c397b3c0a0..42ed2378bc 100644 --- a/src/core/ddsc/src/dds_rhc_default.c +++ b/src/core/ddsc/src/dds_rhc_default.c @@ -621,7 +621,14 @@ static void dds_rhc_default_set_qos (struct ddsi_rhc *rhc_common, const dds_qos_ static bool eval_predicate_sample (const struct dds_rhc_default *rhc, const struct ddsi_serdata *sample, bool (*pred) (const void *sample)) { - ddsi_serdata_to_sample (sample, rhc->qcond_eval_samplebuf, NULL, NULL); + // What to do if deserialization fails? Consider it matching or not? + // + // This is used in query evaluation, so claiming it matches at least allows taking it, + // and at least it allows the application to detect something is amiss. Always + // returning false would likely lead to endless loops in the application because some + // read condition remains triggered. + if (!ddsi_serdata_to_sample (sample, rhc->qcond_eval_samplebuf, NULL, NULL)) + return true; bool ret = pred (rhc->qcond_eval_samplebuf); return ret; } @@ -989,23 +996,30 @@ static bool content_filter_accepts (const dds_reader *reader, const struct ddsi_ case DDS_TOPIC_FILTER_SAMPLE_SAMPLEINFO_ARG: { char *tmp; tmp = ddsi_sertype_alloc_sample (tp->m_stype); - ddsi_serdata_to_sample (sample, tmp, NULL, NULL); - switch (tp->m_filter.mode) + if (!ddsi_serdata_to_sample (sample, tmp, NULL, NULL)) + { + // Samples we can't deserialize are (presumably) best never inserted + ret = false; + } + else { - case DDS_TOPIC_FILTER_NONE: - case DDS_TOPIC_FILTER_SAMPLEINFO_ARG: - assert (0); - case DDS_TOPIC_FILTER_SAMPLE: - ret = (tp->m_filter.f.sample) (tmp); - break; - case DDS_TOPIC_FILTER_SAMPLE_ARG: - ret = (tp->m_filter.f.sample_arg) (tmp, tp->m_filter.arg); - break; - case DDS_TOPIC_FILTER_SAMPLE_SAMPLEINFO_ARG: { - struct dds_sample_info si; - content_filter_make_sampleinfo (&si, sample, inst, wr_iid, iid); - ret = tp->m_filter.f.sample_sampleinfo_arg (tmp, &si, tp->m_filter.arg); - break; + switch (tp->m_filter.mode) + { + case DDS_TOPIC_FILTER_NONE: + case DDS_TOPIC_FILTER_SAMPLEINFO_ARG: + assert (0); + case DDS_TOPIC_FILTER_SAMPLE: + ret = (tp->m_filter.f.sample) (tmp); + break; + case DDS_TOPIC_FILTER_SAMPLE_ARG: + ret = (tp->m_filter.f.sample_arg) (tmp, tp->m_filter.arg); + break; + case DDS_TOPIC_FILTER_SAMPLE_SAMPLEINFO_ARG: { + struct dds_sample_info si; + content_filter_make_sampleinfo (&si, sample, inst, wr_iid, iid); + ret = tp->m_filter.f.sample_sampleinfo_arg (tmp, &si, tp->m_filter.arg); + break; + } } } ddsi_sertype_free_sample (tp->m_stype, tmp, DDS_FREE_ALL); @@ -2922,10 +2936,11 @@ static bool rhc_check_counts_locked (struct dds_rhc_default *rhc, bool check_con { struct rhc_sample *sample = inst->latest->next, * const end = sample; do { - ddsi_serdata_to_sample (sample->sample, rhc->qcond_eval_samplebuf, NULL, NULL); + // Follow error handling choices made in eval_predicate_sample() + const bool asifmatch = !ddsi_serdata_to_sample (sample->sample, rhc->qcond_eval_samplebuf, NULL, NULL); qcmask = 0; for (rciter = rhc->conds; rciter; rciter = rciter->m_next) - if (rciter->m_query.m_filter != 0 && rciter->m_query.m_filter (rhc->qcond_eval_samplebuf)) + if (rciter->m_query.m_filter != 0 && (asifmatch || rciter->m_query.m_filter (rhc->qcond_eval_samplebuf))) qcmask |= rciter->m_query.m_qcmask; assert ((sample->conds & enabled_qcmask) == qcmask); sample = sample->next; diff --git a/src/core/ddsc/src/dds_serdata_default.c b/src/core/ddsc/src/dds_serdata_default.c index a812721158..79bee52841 100644 --- a/src/core/ddsc/src/dds_serdata_default.c +++ b/src/core/ddsc/src/dds_serdata_default.c @@ -343,6 +343,9 @@ static bool gen_serdata_key_from_cdr (dds_istream_t * __restrict is, struct dds_ } /* Construct a serdata from a fragchain received over the network */ +static struct dds_serdata_default *serdata_default_from_ser_common (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all; + static struct dds_serdata_default *serdata_default_from_ser_common (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { const struct dds_sertype_default *tp = (const struct dds_sertype_default *)tpcmn; @@ -366,18 +369,17 @@ static struct dds_serdata_default *serdata_default_from_ser_common (const struct if (!is_valid_xcdr_id (d->hdr.identifier)) goto err; - while (fragchain) + for (const struct ddsi_rdata *frag = fragchain; frag != NULL; frag = frag->nextfrag) { - assert (fragchain->min <= off); - assert (fragchain->maxp1 <= size); - if (fragchain->maxp1 > off) + assert (frag->min <= off); + assert (frag->maxp1 <= size); + if (frag->maxp1 > off) { /* only copy if this fragment adds data */ - const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (fragchain->rmsg, DDSI_RDATA_PAYLOAD_OFF (fragchain)); - serdata_default_append_blob (&d, fragchain->maxp1 - off, payload + off - fragchain->min); - off = fragchain->maxp1; + const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (frag->rmsg, DDSI_RDATA_PAYLOAD_OFF (frag)); + serdata_default_append_blob (&d, frag->maxp1 - off, payload + off - frag->min); + off = frag->maxp1; } - fragchain = fragchain->nextfrag; } const bool needs_bswap = !DDSI_RTPS_CDR_ENC_IS_NATIVE (d->hdr.identifier); diff --git a/src/core/ddsc/tests/readcollect.c b/src/core/ddsc/tests/readcollect.c index a15d819978..eb5e41f7fc 100644 --- a/src/core/ddsc/tests/readcollect.c +++ b/src/core/ddsc/tests/readcollect.c @@ -29,10 +29,12 @@ typedef dds_return_t (*read_op) (dds_entity_t rd_or_cnd, uint32_t maxs, dds_inst static Space_Type1 getdata (const dds_sample_info_t *si, const struct ddsi_sertype *st, struct ddsi_serdata *sd) { Space_Type1 s; + bool ok; if (si->valid_data) - ddsi_serdata_to_sample (sd, &s, NULL, NULL); + ok = ddsi_serdata_to_sample (sd, &s, NULL, NULL); else - ddsi_serdata_untyped_to_sample (st, sd, &s, NULL, NULL); + ok = ddsi_serdata_untyped_to_sample (st, sd, &s, NULL, NULL); + CU_ASSERT_FATAL (ok); return s; } @@ -96,7 +98,7 @@ static void dotest (read_op op) rc = op (rd, INT32_MAX, 0, 0, coll_fail_after_1, &arg1); CU_ASSERT_FATAL (rc == 1); CU_ASSERT_FATAL (arg1.k >= 0 && arg1.k <= 2); - + // same should be true if instance handle is provided, use a different instance just because we can dds_instance_handle_t ih; rc = dds_register_instance (wr, &ih, &(Space_Type1){ .long_1 = (1+arg1.k)%3, .long_2 = 0, .long_3 = 0 }); @@ -107,11 +109,11 @@ static void dotest (read_op op) rc = op (rd, INT32_MAX, ih, 0, coll_fail_after_1, &arg2); CU_ASSERT_FATAL (rc == 1); CU_ASSERT_FATAL (arg2.k == (1+arg1.k)%3); - + assert (op == dds_peek_with_collector || op == dds_read_with_collector || op == dds_take_with_collector); bool isread = (op == dds_read_with_collector); bool isnew = (op == dds_peek_with_collector); - + // check that the remainder is as we expect it Space_Type1 xs[10]; dds_sample_info_t si[10]; diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h index 6c3eca6d1e..c75607d6c4 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_serdata.h @@ -51,10 +51,12 @@ struct ddsi_serdata { /* Serialised size of sample inclusive of DDSI encoding header - uint32_t because the protocol can't handle samples larger than 4GB anyway - FIXME: get the encoding header out of the serialised data */ -typedef uint32_t (*ddsi_serdata_size_t) (const struct ddsi_serdata *d); +typedef uint32_t (*ddsi_serdata_size_t) (const struct ddsi_serdata *d) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Free a serdata (called by unref when refcount goes to 0) */ -typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d); +typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d) + ddsrt_nonnull_all; /* Construct a serdata from a fragchain received over the network - "kind" is KEY or DATA depending on the type of payload @@ -63,20 +65,24 @@ typedef void (*ddsi_serdata_free_t) (struct ddsi_serdata *d); - fragchains may overlap, though I have never seen any DDS implementation actually send such nasty fragments - FIXME: get the encoding header out of the serialised data */ -typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size); +typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Exactly like ddsi_serdata_from_ser_t, but with the data in an iovec and guaranteed absence of overlap */ -typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size); +typedef struct ddsi_serdata * (*ddsi_serdata_from_ser_iov_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Construct a serdata from a keyhash (an SDK_KEY by definition) */ -typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertype *type, const struct ddsi_keyhash *keyhash); +typedef struct ddsi_serdata * (*ddsi_serdata_from_keyhash_t) (const struct ddsi_sertype *type, const struct ddsi_keyhash *keyhash) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Construct a serdata from an application sample - "kind" is KEY or DATA depending on the operation invoked by the application; e.g., write results in kind = DATA, dispose in kind = KEY. The important bit is to not assume anything of the contents of non-key fields if kind = KEY unless additional application knowledge is available */ -typedef struct ddsi_serdata * (*ddsi_serdata_from_sample_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const void *sample); +typedef struct ddsi_serdata * (*ddsi_serdata_from_sample_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const void *sample) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Construct a untyped serdata with just a keyvalue given a normal serdata (either key or data) - used for mapping key values to instance ids in tkmap @@ -86,7 +92,8 @@ typedef struct ddsi_serdata * (*ddsi_serdata_from_sample_t) (const struct ddsi_s field may have any value for a untyped serdata (so in some cases, one can simply do "return ddsi_serdata_ref(d);" */ -typedef struct ddsi_serdata * (*ddsi_serdata_to_untyped_t) (const struct ddsi_serdata *d); +typedef struct ddsi_serdata * (*ddsi_serdata_to_untyped_t) (const struct ddsi_serdata *d) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Fill buffer with 'size' bytes of serialised data, starting from 'off' - 0 <= off < off+sz <= alignup4(size(d)) @@ -94,7 +101,8 @@ typedef struct ddsi_serdata * (*ddsi_serdata_to_untyped_t) (const struct ddsi_se - what to copy for bytes in [size(d), alignup4(size(d))) depends on the serdata implementation, the protocol treats them as undefined - FIXME: get the encoding header out of the serialised data */ -typedef void (*ddsi_serdata_to_ser_t) (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf); +typedef void (*ddsi_serdata_to_ser_t) (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) + ddsrt_nonnull_all; /* Provide a pointer to 'size' bytes of serialised data, starting from 'off' - see ddsi_serdata_to_ser_t above @@ -103,11 +111,13 @@ typedef void (*ddsi_serdata_to_ser_t) (const struct ddsi_serdata *d, size_t off, - multiple calls to to_ser_ref() may be issued in parallel - lazily creating the serialised representation is allowed (though I'm not sure how that would work with knowing the serialised size beforehand ...) */ -typedef struct ddsi_serdata * (*ddsi_serdata_to_ser_ref_t) (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref); +typedef struct ddsi_serdata * (*ddsi_serdata_to_ser_ref_t) (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /* Release a lock on serialised data - ref was previousy filled by ddsi_serdata_to_ser_ref_t */ -typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt_iovec_t *ref); +typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt_iovec_t *ref) + ddsrt_nonnull_all; /* Turn serdata into an application sample (or just the key values if only key values are available); return false on error (typically out-of-memory, but if from_ser doesn't do any @@ -117,18 +127,21 @@ typedef void (*ddsi_serdata_to_ser_unref_t) (struct ddsi_serdata *d, const ddsrt padding) for any data in the sample that needs to be allocated (e.g., strings, sequences); otherwise malloc() is to be used for those. (This allows read/take to be given a block of memory by the caller.) */ -typedef bool (*ddsi_serdata_to_sample_t) (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); +typedef bool (*ddsi_serdata_to_sample_t) (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) + ddsrt_nonnull ((1, 2)) ddsrt_attribute_warn_unused_result; /* Create a sample from a untyped serdata, as returned by serdata_to_untyped. This sample obviously has just the key fields filled in and is used for generating invalid samples. */ -typedef bool (*ddsi_serdata_untyped_to_sample_t) (const struct ddsi_sertype *type, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim); +typedef bool (*ddsi_serdata_untyped_to_sample_t) (const struct ddsi_sertype *type, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) + ddsrt_nonnull ((1, 2, 3)) ddsrt_attribute_warn_unused_result; /* Test key values of two serdatas for equality. The two will have the same ddsi_serdata_ops, but are not necessarily of the same topic (one can decide to never consider them equal if they are of different topics, of course; but the nice thing about _not_ doing that is that all instances with a certain key value with have the same instance id, and that in turn makes computing equijoins across topics much simpler). */ -typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct ddsi_serdata *b); +typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct ddsi_serdata *b) + ddsrt_nonnull_all; /* Print a serdata into the provided buffer (truncating as necessary) - topic is present for supporting printing of "untyped" samples @@ -137,20 +150,23 @@ typedef bool (*ddsi_serdata_eqkey_t) (const struct ddsi_serdata *a, const struct - returns the number of characters (excluding the terminating 0) needed to print it in full (or, as an optimization, it may pretend that it has printed it in full, returning bufsize-1) if it had to truncate) */ -typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertype *type, const struct ddsi_serdata *d, char *buf, size_t size); +typedef size_t (*ddsi_serdata_print_t) (const struct ddsi_sertype *type, const struct ddsi_serdata *d, char *buf, size_t size) + ddsrt_nonnull_all; /* Add keyhash (from serdata) to buffer (forcing md5 when necessary). - key needs to be set within serdata (can already be md5) - buf needs to be at least 16 bytes large */ -typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5); +typedef void (*ddsi_serdata_get_keyhash_t) (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) + ddsrt_nonnull_all; // Used for taking a loaned sample and constructing a serdata around this // takes over ownership of loan on success (leaves it unchanged on failure) -typedef struct ddsi_serdata* (*ddsi_serdata_from_loan_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const char *sample, struct dds_loaned_sample *loaned_sample, bool will_require_cdr); +typedef struct ddsi_serdata* (*ddsi_serdata_from_loan_t) (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const char *sample, struct dds_loaned_sample *loaned_sample, bool will_require_cdr) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; // Used for constructing a serdata from data received on a PSMX -typedef struct ddsi_serdata* (*ddsi_serdata_from_psmx_t) (const struct ddsi_sertype *type, struct dds_loaned_sample *loaned_sample); - +typedef struct ddsi_serdata* (*ddsi_serdata_from_psmx_t) (const struct ddsi_sertype *type, struct dds_loaned_sample *loaned_sample) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; struct ddsi_serdata_ops { ddsi_serdata_eqkey_t eqkey; @@ -177,7 +193,8 @@ struct ddsi_serdata_ops { #define DDSI_SERDATA_HAS_GET_KEYHASH 1 /** @component typesupport_if */ -DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertype *tp, enum ddsi_serdata_kind kind); +DDS_EXPORT void ddsi_serdata_init (struct ddsi_serdata *d, const struct ddsi_sertype *tp, enum ddsi_serdata_kind kind) + ddsrt_nonnull_all; /** * @brief Return a pointer to the keyhash in the message fragchain if it was present, or else NULL. @@ -224,7 +241,10 @@ struct ddsi_serdata *ddsi_serdata_ref_as_type (const struct ddsi_sertype *type, ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) + ddsrt_nonnull_all; + +inline struct ddsi_serdata *ddsi_serdata_ref (const struct ddsi_serdata *serdata_const) { #if defined (__cplusplus) DDSRT_WARNING_GNUC_OFF(old-style-cast) DDSRT_WARNING_CLANG_OFF(old-style-cast) @@ -239,80 +259,125 @@ DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_ref (const struct dds } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline void ddsi_serdata_unref (struct ddsi_serdata *serdata) { +DDS_INLINE_EXPORT inline void ddsi_serdata_unref (struct ddsi_serdata *serdata) + ddsrt_nonnull_all; + +inline void ddsi_serdata_unref (struct ddsi_serdata *serdata) { if (ddsrt_atomic_dec32_ov (&serdata->refc) == 1) serdata->ops->free (serdata); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d) { +DDS_INLINE_EXPORT inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d) + ddsrt_nonnull_all; + +inline uint32_t ddsi_serdata_size (const struct ddsi_serdata *d) { return d->ops->get_size (d); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_from_ser (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { return type->serdata_ops->from_ser (type, kind, fragchain, size); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_from_ser_iov (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, ddsrt_msg_iovlen_t niov, const ddsrt_iovec_t *iov, size_t size) { return type->serdata_ops->from_ser_iov (type, kind, niov, iov, size); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertype *type, const struct ddsi_keyhash *keyhash) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertype *type, const struct ddsi_keyhash *keyhash) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_from_keyhash (const struct ddsi_sertype *type, const struct ddsi_keyhash *keyhash) { return type->serdata_ops->from_keyhash (type, keyhash); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const void *sample) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const void *sample) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_from_sample (const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const void *sample) { return type->serdata_ops->from_sample (type, kind, sample); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_untyped (const struct ddsi_serdata *d) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_untyped (const struct ddsi_serdata *d) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_to_untyped (const struct ddsi_serdata *d) { struct ddsi_serdata * const d1 = d->ops->to_untyped (d); assert (d1->loan == NULL); return d1; } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) { +DDS_INLINE_EXPORT inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) + ddsrt_nonnull_all; + +inline void ddsi_serdata_to_ser (const struct ddsi_serdata *d, size_t off, size_t sz, void *buf) { d->ops->to_ser (d, off, sz, buf); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_ser_ref (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref) { +DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_to_ser_ref (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref) + ddsrt_nonnull_all ddsrt_attribute_warn_unused_result; + +inline struct ddsi_serdata *ddsi_serdata_to_ser_ref (const struct ddsi_serdata *d, size_t off, size_t sz, ddsrt_iovec_t *ref) { return d->ops->to_ser_ref (d, off, sz, ref); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const ddsrt_iovec_t *ref) { +DDS_INLINE_EXPORT inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const ddsrt_iovec_t *ref) + ddsrt_nonnull_all; + +inline void ddsi_serdata_to_ser_unref (struct ddsi_serdata *d, const ddsrt_iovec_t *ref) { d->ops->to_ser_unref (d, ref); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { +DDS_INLINE_EXPORT inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) + ddsrt_nonnull ((1, 2)) ddsrt_attribute_warn_unused_result; + +inline bool ddsi_serdata_to_sample (const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { return d->ops->to_sample (d, sample, bufptr, buflim); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline bool ddsi_serdata_untyped_to_sample (const struct ddsi_sertype *type, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { +DDS_INLINE_EXPORT inline bool ddsi_serdata_untyped_to_sample (const struct ddsi_sertype *type, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) + ddsrt_nonnull ((1, 2, 3)) ddsrt_attribute_warn_unused_result; + +inline bool ddsi_serdata_untyped_to_sample (const struct ddsi_sertype *type, const struct ddsi_serdata *d, void *sample, void **bufptr, void *buflim) { return d->ops->untyped_to_sample (type, d, sample, bufptr, buflim); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b) { +DDS_INLINE_EXPORT inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b) + ddsrt_nonnull_all; + +inline bool ddsi_serdata_eqkey (const struct ddsi_serdata *a, const struct ddsi_serdata *b) { return a->ops->eqkey (a, b); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline size_t ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size) { +DDS_INLINE_EXPORT inline size_t ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size) + ddsrt_nonnull_all; + +inline size_t ddsi_serdata_print (const struct ddsi_serdata *d, char *buf, size_t size) { return d->ops->print (d->type, d, buf, size); } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline size_t ddsi_serdata_print_untyped (const struct ddsi_sertype *type, const struct ddsi_serdata *d, char *buf, size_t size) { +DDS_INLINE_EXPORT inline size_t ddsi_serdata_print_untyped (const struct ddsi_sertype *type, const struct ddsi_serdata *d, char *buf, size_t size) + ddsrt_nonnull_all; + +inline size_t ddsi_serdata_print_untyped (const struct ddsi_sertype *type, const struct ddsi_serdata *d, char *buf, size_t size) { if (d->ops->print) return d->ops->print (type, d, buf, size); else @@ -323,22 +388,24 @@ DDS_INLINE_EXPORT inline size_t ddsi_serdata_print_untyped (const struct ddsi_se } /** @component typesupport_if */ -DDS_INLINE_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) { +DDS_INLINE_EXPORT inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) + ddsrt_nonnull_all; + +inline void ddsi_serdata_get_keyhash (const struct ddsi_serdata *d, struct ddsi_keyhash *buf, bool force_md5) { d->ops->get_keyhash (d, buf, force_md5); } DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_loaned_sample(const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const char *sample, struct dds_loaned_sample *loan, bool will_require_cdr) ddsrt_nonnull_all; /** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_loaned_sample(const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const char *sample, struct dds_loaned_sample *loan, bool will_require_cdr) +inline struct ddsi_serdata *ddsi_serdata_from_loaned_sample(const struct ddsi_sertype *type, enum ddsi_serdata_kind kind, const char *sample, struct dds_loaned_sample *loan, bool will_require_cdr) { return type->serdata_ops->from_loaned_sample(type, kind, sample, loan, will_require_cdr); } DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_psmx(const struct ddsi_sertype *type, struct dds_loaned_sample *data) ddsrt_nonnull_all; -/** @component typesupport_if */ -DDS_INLINE_EXPORT inline struct ddsi_serdata *ddsi_serdata_from_psmx(const struct ddsi_sertype *type, struct dds_loaned_sample *data) +inline struct ddsi_serdata *ddsi_serdata_from_psmx(const struct ddsi_sertype *type, struct dds_loaned_sample *data) { return type->serdata_ops->from_psmx(type, data); } diff --git a/src/core/ddsi/src/ddsi_gc.c b/src/core/ddsi/src/ddsi_gc.c index 5be145ac69..4df45d7564 100644 --- a/src/core/ddsi/src/ddsi_gc.c +++ b/src/core/ddsi/src/ddsi_gc.c @@ -35,14 +35,15 @@ struct ddsi_gcreq_queue { struct ddsi_thread_state *thrst; }; -static void threads_vtime_gather_for_wait (const struct ddsi_domaingv *gv, uint32_t *nivs, struct ddsi_idx_vtime *ivs, struct ddsi_thread_states_list *cur) +static void threads_vtime_gather_for_wait (const struct ddsi_domaingv *gv, uint32_t *nivs, struct ddsi_idx_vtime *ivs, struct ddsi_thread_states_list *tslist) { /* copy vtimes of threads, skipping those that are sleeping */ #ifndef NDEBUG - const uint32_t nthreads = cur->nthreads; + const uint32_t nthreads = tslist->nthreads; #endif + struct ddsi_thread_states_list *cur; uint32_t dstidx; - for (dstidx = 0; cur; cur = cur->next) + for (dstidx = 0, cur = tslist; cur; cur = cur->next) { for (uint32_t i = 0; i < DDSI_THREAD_STATE_BATCH; i++) { diff --git a/src/core/ddsi/src/ddsi_security_msg.c b/src/core/ddsi/src/ddsi_security_msg.c index ec00b336f3..807b3a6f21 100644 --- a/src/core/ddsi/src/ddsi_security_msg.c +++ b/src/core/ddsi/src/ddsi_security_msg.c @@ -175,7 +175,7 @@ int ddsi_volatile_secure_data_filter(struct ddsi_writer *wr, struct ddsi_proxy_r assert(serdata); /* guid_offset + 4 because 4 bytes header is at 0 */ - (void)ddsi_serdata_to_ser_ref(serdata, guid_offset + 4, sizeof(ddsi_guid_t), &guid_ref); + struct ddsi_serdata *serdata_ref = ddsi_serdata_to_ser_ref(serdata, guid_offset + 4, sizeof(ddsi_guid_t), &guid_ref); assert(guid_ref.iov_len == sizeof(ddsi_guid_t)); assert(guid_ref.iov_base); msg_guid = (ddsi_guid_t*)guid_ref.iov_base; @@ -187,7 +187,7 @@ int ddsi_volatile_secure_data_filter(struct ddsi_writer *wr, struct ddsi_proxy_r pass = ddsi_guid_eq(msg_guid, &pp_guid); } - ddsi_serdata_to_ser_unref(serdata, &guid_ref); + ddsi_serdata_to_ser_unref(serdata_ref, &guid_ref); return pass; } diff --git a/src/core/ddsi/src/ddsi_serdata_cdr.c b/src/core/ddsi/src/ddsi_serdata_cdr.c index e809130057..64df0aac46 100644 --- a/src/core/ddsi/src/ddsi_serdata_cdr.c +++ b/src/core/ddsi/src/ddsi_serdata_cdr.c @@ -128,6 +128,9 @@ static inline bool is_valid_xcdr_id (unsigned short cdr_identifier) } /* Construct a serdata from a fragchain received over the network */ +static struct ddsi_serdata_cdr *serdata_cdr_from_ser_common (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all; + static struct ddsi_serdata_cdr *serdata_cdr_from_ser_common (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { assert (kind == SDK_DATA); @@ -152,18 +155,17 @@ static struct ddsi_serdata_cdr *serdata_cdr_from_ser_common (const struct ddsi_s if (!is_valid_xcdr_id (d->hdr.identifier)) goto err; - while (fragchain) + for (const struct ddsi_rdata *frag = fragchain; frag != NULL; frag = frag->nextfrag) { - assert (fragchain->min <= off); - assert (fragchain->maxp1 <= size); - if (fragchain->maxp1 > off) + assert (frag->min <= off); + assert (frag->maxp1 <= size); + if (frag->maxp1 > off) { /* only copy if this fragment adds data */ - const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (fragchain->rmsg, DDSI_RDATA_PAYLOAD_OFF (fragchain)); - serdata_cdr_append_blob (&d, fragchain->maxp1 - off, payload + off - fragchain->min); - off = fragchain->maxp1; + const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (frag->rmsg, DDSI_RDATA_PAYLOAD_OFF (frag)); + serdata_cdr_append_blob (&d, frag->maxp1 - off, payload + off - frag->min); + off = frag->maxp1; } - fragchain = fragchain->nextfrag; } const bool needs_bswap = !DDSI_RTPS_CDR_ENC_IS_NATIVE (d->hdr.identifier); diff --git a/src/core/ddsi/src/ddsi_serdata_plist.c b/src/core/ddsi/src/ddsi_serdata_plist.c index 911618b5f5..34c3869d15 100644 --- a/src/core/ddsi/src/ddsi_serdata_plist.c +++ b/src/core/ddsi/src/ddsi_serdata_plist.c @@ -99,6 +99,9 @@ static struct ddsi_serdata *serdata_plist_fix (const struct ddsi_sertype_plist * return &d->c; } +static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all; + static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { const struct ddsi_sertype_plist *tp = (const struct ddsi_sertype_plist *) tpcmn; @@ -108,20 +111,19 @@ static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertype *t uint32_t off = 4; /* must skip the CDR header */ assert (fragchain->min == 0); assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ - while (fragchain) + for (const struct ddsi_rdata *frag = fragchain; frag != NULL; frag = frag->nextfrag) { - assert (fragchain->min <= off); - assert (fragchain->maxp1 <= size); - if (fragchain->maxp1 > off) + assert (frag->min <= off); + assert (frag->maxp1 <= size); + if (frag->maxp1 > off) { /* only copy if this fragment adds data */ - const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (fragchain->rmsg, DDSI_RDATA_PAYLOAD_OFF (fragchain)); - uint32_t n = fragchain->maxp1 - off; - memcpy (d->data + d->pos, payload + off - fragchain->min, n); + const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (frag->rmsg, DDSI_RDATA_PAYLOAD_OFF (frag)); + uint32_t n = frag->maxp1 - off; + memcpy (d->data + d->pos, payload + off - frag->min, n); d->pos += n; - off = fragchain->maxp1; + off = frag->maxp1; } - fragchain = fragchain->nextfrag; } return serdata_plist_fix (tp, d); } diff --git a/src/core/ddsi/src/ddsi_serdata_pserop.c b/src/core/ddsi/src/ddsi_serdata_pserop.c index 1241e66feb..3bee78e371 100644 --- a/src/core/ddsi/src/ddsi_serdata_pserop.c +++ b/src/core/ddsi/src/ddsi_serdata_pserop.c @@ -106,6 +106,9 @@ static struct ddsi_serdata *serdata_pserop_fix (const struct ddsi_sertype_pserop return &d->c; } +static struct ddsi_serdata *serdata_pserop_from_ser (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) + ddsrt_nonnull_all; + static struct ddsi_serdata *serdata_pserop_from_ser (const struct ddsi_sertype *tpcmn, enum ddsi_serdata_kind kind, const struct ddsi_rdata *fragchain, size_t size) { const struct ddsi_sertype_pserop *tp = (const struct ddsi_sertype_pserop *)tpcmn; @@ -115,20 +118,19 @@ static struct ddsi_serdata *serdata_pserop_from_ser (const struct ddsi_sertype * uint32_t off = 4; /* must skip the CDR header */ assert (fragchain->min == 0); assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */ - while (fragchain) + for (const struct ddsi_rdata *frag = fragchain; frag != NULL; frag = frag->nextfrag) { - assert (fragchain->min <= off); - assert (fragchain->maxp1 <= size); - if (fragchain->maxp1 > off) + assert (frag->min <= off); + assert (frag->maxp1 <= size); + if (frag->maxp1 > off) { /* only copy if this fragment adds data */ - const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (fragchain->rmsg, DDSI_RDATA_PAYLOAD_OFF (fragchain)); - uint32_t n = fragchain->maxp1 - off; - memcpy (d->data + d->pos, payload + off - fragchain->min, n); + const unsigned char *payload = DDSI_RMSG_PAYLOADOFF (frag->rmsg, DDSI_RDATA_PAYLOAD_OFF (frag)); + uint32_t n = frag->maxp1 - off; + memcpy (d->data + d->pos, payload + off - frag->min, n); d->pos += n; - off = fragchain->maxp1; + off = frag->maxp1; } - fragchain = fragchain->nextfrag; } return serdata_pserop_fix (tp, d); } diff --git a/src/core/ddsi/src/ddsi_tcp.c b/src/core/ddsi/src/ddsi_tcp.c index 1f7d90d373..0e065daa3b 100644 --- a/src/core/ddsi/src/ddsi_tcp.c +++ b/src/core/ddsi/src/ddsi_tcp.c @@ -816,6 +816,9 @@ static dds_return_t ddsi_tcp_create_conn (struct ddsi_tran_conn **conn_out, stru return DDS_RETCODE_OK; } +#if defined __GNUC__ && __GNUC__ >= 13 +DDSRT_WARNING_GNUC_OFF (analyzer-fd-leak) +#endif static int ddsi_tcp_listen (struct ddsi_tran_listener * listener) { #ifdef DDS_HAS_SSL @@ -833,6 +836,9 @@ static int ddsi_tcp_listen (struct ddsi_tran_listener * listener) return ret; } +#if defined __GNUC__ && __GNUC__ >= 13 +DDSRT_WARNING_GNUC_ON (analyzer-fd-leak) +#endif static struct ddsi_tran_conn * ddsi_tcp_accept (struct ddsi_tran_listener * listener) { diff --git a/src/core/ddsi/src/ddsi_typelookup.c b/src/core/ddsi/src/ddsi_typelookup.c index 1bea696983..552610c186 100644 --- a/src/core/ddsi/src/ddsi_typelookup.c +++ b/src/core/ddsi/src/ddsi_typelookup.c @@ -276,7 +276,12 @@ void ddsi_tl_handle_request (struct ddsi_domaingv *gv, struct ddsi_serdata *d) DDS_Builtin_TypeLookup_Request req; memset (&req, 0, sizeof (req)); - ddsi_serdata_to_sample (d, &req, NULL, NULL); + if (!ddsi_serdata_to_sample (d, &req, NULL, NULL)) + { + GVTRACE (" handle-tl-req deserialization failed"); + return; + } + if (req.data._d != DDS_Builtin_TypeLookup_getTypes_HashId) { GVTRACE (" handle-tl-req wr "PGUIDFMT " unknown req-type %"PRIi32, PGUID (from_guid (&req.header.requestId.writer_guid)), req.data._d); @@ -384,7 +389,11 @@ void ddsi_tl_handle_reply (struct ddsi_domaingv *gv, struct ddsi_serdata *d) DDS_Builtin_TypeLookup_Reply reply; memset (&reply, 0, sizeof (reply)); - ddsi_serdata_to_sample (d, &reply, NULL, NULL); + if (!ddsi_serdata_to_sample (d, &reply, NULL, NULL)) + { + GVTRACE (" handle-tl-req deserialization failed"); + return; + } if (reply.return_data._d != DDS_Builtin_TypeLookup_getTypes_HashId) { GVTRACE (" handle-tl-reply wr "PGUIDFMT " unknown reply-type %"PRIi32, PGUID (from_guid (&reply.header.relatedRequestId.writer_guid)), reply.return_data._d); diff --git a/src/core/xtests/rhc_torture/rhc_torture.c b/src/core/xtests/rhc_torture/rhc_torture.c index dc865eb048..738c537ea1 100644 --- a/src/core/xtests/rhc_torture/rhc_torture.c +++ b/src/core/xtests/rhc_torture/rhc_torture.c @@ -145,7 +145,8 @@ static uint64_t store (struct ddsi_tkmap *tkmap, struct dds_rhc *rhc, struct dds char si_d = (sd->statusinfo & DDSI_STATUSINFO_DISPOSE) ? 'D' : '.'; char si_u = (sd->statusinfo & DDSI_STATUSINFO_UNREGISTER) ? 'U' : '.'; memset (&d, 0, sizeof (d)); - ddsi_serdata_to_sample (sd, &d, NULL, NULL); + if (!ddsi_serdata_to_sample (sd, &d, NULL, NULL)) + abort (); (void) print_tstamp (buf, sizeof (buf), sd->timestamp.v); if (sd->kind == SDK_KEY) printf ("STORE %c%c %16"PRIx64" %16"PRIx64" %2"PRId32" %6s %s\n", si_u, si_d, iid, wr->e.iid, d.k, "_", buf); @@ -651,7 +652,7 @@ static void test_conditions (dds_entity_t pp, dds_entity_t tp, const int count, if (conds[ci] <= 0) abort (); rhcconds[ci] = get_condaddr (conds[ci]); if (print) { - char buf[18]; + char buf[19]; snprintf (buf, sizeof (buf), "conds[%d]", ci); print_cond_w_addr (buf, conds[ci]); } diff --git a/src/core/xtests/symbol_export/symbol_export.c b/src/core/xtests/symbol_export/symbol_export.c index bcc880f3c1..c425a740d5 100644 --- a/src/core/xtests/symbol_export/symbol_export.c +++ b/src/core/xtests/symbol_export/symbol_export.c @@ -74,6 +74,8 @@ #include "dds__write.h" // dds_write_impl, dds_writecdr_impl DDSRT_WARNING_DEPRECATED_OFF +DDSRT_WARNING_GNUC_OFF (unused-result) +DDSRT_WARNING_CLANG_OFF (unused-result) DDSRT_WARNING_CLANG_OFF(unused-result) DDSRT_WARNING_GNUC_OFF(unused-result) diff --git a/src/idl/src/file.c b/src/idl/src/file.c index 79e97d846e..982d97edad 100644 --- a/src/idl/src/file.c +++ b/src/idl/src/file.c @@ -477,7 +477,8 @@ idl_retcode_t idl_generate_out_file(const char *path, const char *output_dir, co if (!(basename = idl_strndup(file, ext ? (size_t)(ext-file) : strlen(file)))) goto err_basename; - /* replace backslashes by forward slashes */ + /* replace backslashes by forward slashes; assert for gcc 13 static analyzer */ + assert (dir != empty || *dir == '\0'); for (char *ptr = dir; *ptr; ptr++) { if (*ptr == '\\') *ptr = '/'; diff --git a/src/tools/idlc/xtests/Compile.cmake b/src/tools/idlc/xtests/Compile.cmake index a3bd5c1237..17f939b594 100644 --- a/src/tools/idlc/xtests/Compile.cmake +++ b/src/tools/idlc/xtests/Compile.cmake @@ -52,6 +52,9 @@ else() set(ENV{LIBRARY_PATH} "$ENV{LIBRARY_PATH}:$ENV{CDDS_LIB_PATH}") set(_output_flag "-o") set(_lib_path "") + if(APPLE) + list(APPEND _lib_path "-rpath" "$ENV{CDDS_LIB_PATH}") + endif() set(_lib "-lddsc") set(_fdbg "-g") set(_fwarn "-Wall") @@ -141,4 +144,4 @@ foreach(_source ${_sources}) message(FATAL_ERROR "Test failed ${_source}: ${_result} ${_error}") endif() -endforeach() \ No newline at end of file +endforeach() diff --git a/src/tools/idlpp/src/expand.c b/src/tools/idlpp/src/expand.c index 27b6b157f0..30c4e1ffad 100644 --- a/src/tools/idlpp/src/expand.c +++ b/src/tools/idlpp/src/expand.c @@ -479,6 +479,11 @@ static char * print_macro_arg( * This routine is only called from above print_macro_inf(). */ { +#if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wformat-overflow\"") +_Pragma("GCC diagnostic ignored \"-Warray-bounds\"") +#endif LOCATION * loc = m_inf->loc_args + argn; out += sprintf( out, "/*%s%s:%d-%d", real_arg ? "!" : (start ? "<" : "") @@ -495,6 +500,9 @@ static char * print_macro_arg( out = stpcpy( out, "*/"); return out; +#if defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic pop") +#endif } static char * chk_magic_balance( diff --git a/src/tools/idlpp/src/system.c b/src/tools/idlpp/src/system.c index ba3e7654d6..9c55fc3abe 100644 --- a/src/tools/idlpp/src/system.c +++ b/src/tools/idlpp/src/system.c @@ -2517,6 +2517,10 @@ static char * norm_path( * open_file(). */ { +#if !defined (__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wstringop-overread\"") +#endif char * norm_name; /* The path-list converted */ char * start; char * cp1; @@ -2771,6 +2775,9 @@ static char * norm_path( } return norm_name; +#if !defined (__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic pop") +#endif } #if SYS_FAMILY == SYS_UNIX @@ -4669,6 +4676,12 @@ static void do_preprocessed( void) * Install macros according the #define directives. */ { +#if !defined (__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wnonnull\"") +_Pragma("GCC diagnostic ignored \"-Warray-bounds\"") +_Pragma("GCC diagnostic ignored \"-Wstringop-overread\"") +#endif const char * corrupted = "This preprocessed file is corrupted"; /* _F_ */ FILEINFO * file; @@ -4753,6 +4766,9 @@ static void do_preprocessed( void) unget_ch(); /* infile == file */ } file->bptr = file->buffer + strlen( file->buffer); +#if !defined (__clang__) && defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 1300 && ((__GNUC__ * 100) + __GNUC_MINOR__) < 1302 +_Pragma("GCC diagnostic pop") +#endif } static int do_debug( diff --git a/src/ucunit/src/ucunit.c b/src/ucunit/src/ucunit.c index 3f547ec149..ee6a3783da 100644 --- a/src/ucunit/src/ucunit.c +++ b/src/ucunit/src/ucunit.c @@ -53,6 +53,8 @@ void CU_assertImplementation (bool value, int line, const char *expr, const char failure_count++; cur_test->nfailures++; struct CU_FailureRecord *fr = malloc (sizeof (*fr)); + if (fr == NULL) + abort (); fr->file = file; fr->line = line; fr->expr = expr; @@ -93,6 +95,8 @@ static char *ucunit_strdup (const char *s) { size_t l = strlen (s) + 1; char *n = malloc (l); + if (n == NULL) + abort (); memcpy (n, s, l); return n; } @@ -105,6 +109,8 @@ CU_pSuite CU_add_suite (const char *strName, CU_InitializeFunc pInit, CU_Cleanup if (cur != NULL) return cur; cur = malloc (sizeof (*cur)); + if (cur == NULL) + abort (); cur->name = ucunit_strdup (strName); cur->init = pInit; cur->cleanup = pClean; @@ -145,6 +151,8 @@ CU_pTest CU_add_test (CU_pSuite pSuite, const char *strName, CU_TestFunc pTestFu if (cur != NULL) return cur; cur = malloc (sizeof (*cur)); + if (cur == NULL) + abort (); cur->name = ucunit_strdup (strName); cur->testfunc = pTestFunc; cur->next = NULL;