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;
 | 
			
		||||
  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 */
 | 
			
		||||
  assert (fragchain->min == 0);
 | 
			
		||||
  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;
 | 
			
		||||
  assert (niov >= 1);
 | 
			
		||||
  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);
 | 
			
		||||
  d->pos += (uint32_t) iov[0].iov_len - 4;
 | 
			
		||||
  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)
 | 
			
		||||
{
 | 
			
		||||
  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 = {
 | 
			
		||||
    .identifier = CDR_BE,
 | 
			
		||||
  const struct { uint16_t identifier, options; nn_parameter_t par; ddsi_keyhash_t kh; nn_parameter_t sentinel; } in = {
 | 
			
		||||
    .identifier = PL_CDR_BE,
 | 
			
		||||
    .options = 0,
 | 
			
		||||
    .par = {
 | 
			
		||||
      .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) };
 | 
			
		||||
  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);
 | 
			
		||||
    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->statusinfo = statusinfo;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue