plist handling of invalid input and keyhashes
This fixes some issues with the new discovery data ("plist" topics) discovered on interoperating with some other DDS implementations: * The interpretation of a keyhash as if it were a valid sample was wrong in various ways: inconsistent endianness, incorrect encoding identifier and a missing sentinel. As Cyclone follows the spec and always provides a well-formed payload, the problem only surfaces when interoperating with implementations that expect the recipient to make do with a keyhash. * Various paths failed to check for failure causing potential null pointer dereferences. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
eb7e5e3a87
commit
52edbe94e9
2 changed files with 19 additions and 4 deletions
|
@ -102,6 +102,8 @@ static struct ddsi_serdata *serdata_plist_from_ser (const struct ddsi_sertopic *
|
||||||
{
|
{
|
||||||
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
||||||
struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)));
|
struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, NN_RMSG_PAYLOADOFF (fragchain->rmsg, NN_RDATA_PAYLOAD_OFF (fragchain)));
|
||||||
|
if (d == NULL)
|
||||||
|
return NULL;
|
||||||
uint32_t off = 4; /* must skip the CDR header */
|
uint32_t off = 4; /* must skip the CDR header */
|
||||||
assert (fragchain->min == 0);
|
assert (fragchain->min == 0);
|
||||||
assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */
|
assert (fragchain->maxp1 >= off); /* CDR header must be in first fragment */
|
||||||
|
@ -128,6 +130,8 @@ static struct ddsi_serdata *serdata_plist_from_ser_iov (const struct ddsi_sertop
|
||||||
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
||||||
assert (niov >= 1);
|
assert (niov >= 1);
|
||||||
struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, iov[0].iov_base);
|
struct ddsi_serdata_plist *d = serdata_plist_new (tp, kind, size, iov[0].iov_base);
|
||||||
|
if (d == NULL)
|
||||||
|
return NULL;
|
||||||
memcpy (d->data + d->pos, (const char *) iov[0].iov_base + 4, iov[0].iov_len - 4);
|
memcpy (d->data + d->pos, (const char *) iov[0].iov_base + 4, iov[0].iov_len - 4);
|
||||||
d->pos += (uint32_t) iov[0].iov_len - 4;
|
d->pos += (uint32_t) iov[0].iov_len - 4;
|
||||||
for (ddsrt_msg_iovlen_t i = 1; i < niov; i++)
|
for (ddsrt_msg_iovlen_t i = 1; i < niov; i++)
|
||||||
|
@ -141,14 +145,18 @@ static struct ddsi_serdata *serdata_plist_from_ser_iov (const struct ddsi_sertop
|
||||||
static struct ddsi_serdata *serdata_plist_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash)
|
static struct ddsi_serdata *serdata_plist_from_keyhash (const struct ddsi_sertopic *tpcmn, const ddsi_keyhash_t *keyhash)
|
||||||
{
|
{
|
||||||
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
const struct ddsi_sertopic_plist *tp = (const struct ddsi_sertopic_plist *) tpcmn;
|
||||||
const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; } in = {
|
const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; nn_parameter_t sentinel; } in = {
|
||||||
.identifier = CDR_BE,
|
.identifier = PL_CDR_BE,
|
||||||
.options = 0,
|
.options = 0,
|
||||||
.par = {
|
.par = {
|
||||||
.parameterid = ddsrt_toBE2u (tp->keyparam),
|
.parameterid = ddsrt_toBE2u (tp->keyparam),
|
||||||
.length = sizeof (*keyhash)
|
.length = ddsrt_toBE2u ((uint16_t) sizeof (*keyhash))
|
||||||
},
|
},
|
||||||
*keyhash
|
.kh = *keyhash,
|
||||||
|
.sentinel = {
|
||||||
|
.parameterid = ddsrt_toBE2u (PID_SENTINEL),
|
||||||
|
.length = 0
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const ddsrt_iovec_t iov = { .iov_base = (void *) &in, .iov_len = sizeof (in) };
|
const ddsrt_iovec_t iov = { .iov_base = (void *) &in, .iov_len = sizeof (in) };
|
||||||
return serdata_plist_from_ser_iov (tpcmn, SDK_KEY, 1, &iov, sizeof (in) - 4);
|
return serdata_plist_from_ser_iov (tpcmn, SDK_KEY, 1, &iov, sizeof (in) - 4);
|
||||||
|
|
|
@ -1534,6 +1534,13 @@ int builtins_dqueue_handler (const struct nn_rsample_info *sampleinfo, const str
|
||||||
PGUID (srcguid), sampleinfo->seq);
|
PGUID (srcguid), sampleinfo->seq);
|
||||||
goto done_upd_deliv;
|
goto done_upd_deliv;
|
||||||
}
|
}
|
||||||
|
if (d == NULL)
|
||||||
|
{
|
||||||
|
GVLOG (DDS_LC_DISCOVERY | DDS_LC_WARNING, "data(builtin, vendor %u.%u): "PGUIDFMT" #%"PRId64": deserialization failed\n",
|
||||||
|
sampleinfo->rst->vendor.id[0], sampleinfo->rst->vendor.id[1],
|
||||||
|
PGUID (srcguid), sampleinfo->seq);
|
||||||
|
goto done_upd_deliv;
|
||||||
|
}
|
||||||
|
|
||||||
d->timestamp = (sampleinfo->timestamp.v != DDSRT_WCTIME_INVALID.v) ? sampleinfo->timestamp : ddsrt_time_wallclock ();
|
d->timestamp = (sampleinfo->timestamp.v != DDSRT_WCTIME_INVALID.v) ? sampleinfo->timestamp : ddsrt_time_wallclock ();
|
||||||
d->statusinfo = statusinfo;
|
d->statusinfo = statusinfo;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue