diff options
author | Jon Schlueter <jschlueter@redhat.com> | 2015-10-07 21:29:30 -0400 |
---|---|---|
committer | Jon Schlueter <jschlueter@redhat.com> | 2015-10-07 21:32:16 -0400 |
commit | ddcc52b5541ed662ecb8399a364a3eb5b6234a32 (patch) | |
tree | e1daead4bdd1001e1bceb42571fe3b5a52aa4025 /driver_ais.c | |
parent | ee67d00957fa58527f33cd1772ae8c05c317db15 (diff) | |
download | gpsd-ddcc52b5541ed662ecb8399a364a3eb5b6234a32.tar.gz |
AIS: Add better handling of non byte aligned data blobs
I ran into a problem with the type 8 unstructured data. When the number
of bits available is not dividable by 8, the last byte may contain
random bits. I would expect the bits beyond the valid range to be 0.
An example of this can be found in the following message:
!AIVDM,3,1,4,A,85PH6TAKfDOkp95`nCRt5w<:qFUiaihFhBc7s4AHGsQ,0*40
!AIVDM,3,2,4,A,DcMJM18k6<=m7rwVm3b5RRWEskwJWej8uP<0:W5K6PA,0*61
!AIVDM,3,3,4,A,gPs<dwulp,4*14
The current version decodes this to:
{"class":"AIS","device":"stdin","type":8,"repeat":0,"mmsi":369493649,"scaled":true,"dac":366,"fid":57,"data":"510:47f3e09168d938bc17f30ae56971a71c16c12ac7ec44585fb854add69d048cc630dd47ebf9b50ea1628a757bcff6a7b7223d80c00a9c56c6811be0eccb3ff74e"}
The 510 bits of data are 63 full bytes and then 6 remaining bits. The
last byte has value: 4e, which is 0100 1110. I would expect 4c, 0100 1100.
To fix this, the following patch could be applied. Please note that the
problem might also be present in other message types, but I have not
encountered any problems in other message types in the 1 million
messages I have in my test dataset. Message types that could be impacted
are: 6, 17, 25 and 26, as they all use the same memcpy to get
unstructured data.
Identified by: Stefan Roels <sroels-gpsd-dev@42solutions.nl>
Added new sample entry to sample.aivdm that exercises this case
Had to regenerate large ais test data log
Diffstat (limited to 'driver_ais.c')
-rw-r--r-- | driver_ais.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/driver_ais.c b/driver_ais.c index 535a420f..a5c26c0a 100644 --- a/driver_ais.c +++ b/driver_ais.c @@ -736,10 +736,16 @@ bool ais_binary_decode(const struct gpsd_errout_t *errout, } } /* land here if we failed to match a known DAC/FID */ - if (!ais->type8.structured) - (void)memcpy(ais->type8.bitdata, - (char *)bits + (56 / CHAR_BIT), - BITS_TO_BYTES(ais->type8.bitcount)); + if (!ais->type8.structured) { + size_t number_of_bytes = BITS_TO_BYTES(ais->type8.bitcount); + (void)memcpy(ais->type8.bitdata, + (char *)bits + (56 / CHAR_BIT), + number_of_bytes); + size_t valid_bits_in_last_byte = ais->type8.bitcount % CHAR_BIT; + if(valid_bits_in_last_byte>0) + ais->type8.bitdata[number_of_bytes-1] &= (0xFF + << (8-valid_bits_in_last_byte)); + } break; case 9: /* Standard SAR Aircraft Position Report */ PERMISSIVE_LENGTH_CHECK(168); |