Skip to content

Commit dc966aa

Browse files
committed
drivers/driver_nmea2000.c: Fix issue 356, skyview buffer overrun.
1 parent f71a58b commit dc966aa

1 file changed

Lines changed: 71 additions & 52 deletions

File tree

drivers/driver_nmea2000.c

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
* Message contents can be had from canboat/analyzer:
1313
* analyzer -explain
1414
*
15-
* This file is Copyright 2012 by the GPSD project
15+
* This file is Copyright by the GPSD project
1616
* SPDX-License-Identifier: BSD-2-clause
1717
*/
1818

19-
#include "../include/gpsd_config.h" /* must be before all includes */
19+
#include "../include/gpsd_config.h" // must be before all includes
2020

2121
#if defined(NMEA2000_ENABLE)
2222

@@ -68,7 +68,7 @@ typedef struct PGN
6868

6969
#if LOG_FILE
7070
FILE *logFile = NULL;
71-
#endif /* of if LOG_FILE */
71+
#endif // of if LOG_FILE
7272

7373
extern bool __attribute__ ((weak)) gpsd_add_device(const char *device_name,
7474
bool flag_nowait);
@@ -89,14 +89,14 @@ static int scale_int(int32_t var, const int64_t factor)
8989
static void print_data(struct gps_context_t *context,
9090
unsigned char *buffer, int len, PGN *pgn)
9191
{
92-
if ((libgps_debuglevel >= LOG_IO) != 0) {
93-
int l1, l2, ptr;
92+
if (LOG_IO <= libgps_debuglevel) {
93+
int l1;
9494
char bu[128];
9595

96-
ptr = 0;
97-
l2 = sprintf(&bu[ptr], "got data:%6u:%3d: ", pgn->pgn, len);
96+
int ptr = 0;
97+
int l2 = sprintf(&bu[ptr], "got data:%6u:%3d: ", pgn->pgn, len);
9898
ptr += l2;
99-
for (l1=0;l1<len;l1++) {
99+
for (l1 = 0; l1 < len; l1++) {
100100
if (((l1 % 20) == 0) && (l1 != 0)) {
101101
GPSD_LOG(LOG_IO, &context->errout, "%s\n", bu);
102102
ptr = 0;
@@ -276,7 +276,7 @@ static gps_mask_t hnd_127258(unsigned char *bu, int len, PGN *pgn,
276276
struct gps_device_t *session)
277277
{
278278
print_data(session->context, bu, len, pgn);
279-
/* FIXME? Get magnetic variation */
279+
// FIXME? Get magnetic variation
280280
GPSD_LOG(LOG_DATA, &session->context->errout,
281281
"pgn %6d(%3d):\n", pgn->pgn, session->driver.nmea2000.unit);
282282
return(0);
@@ -358,7 +358,7 @@ static gps_mask_t hnd_126992(unsigned char *bu, int len, PGN *pgn,
358358
{
359359
// uint8_t sid;
360360
// uint8_t source;
361-
uint64_t usecs; /* time in us */
361+
uint64_t usecs; // time in us
362362

363363
print_data(session->context, bu, len, pgn);
364364
GPSD_LOG(LOG_DATA, &session->context->errout,
@@ -434,31 +434,47 @@ static gps_mask_t hnd_129540(unsigned char *bu, int len, PGN *pgn,
434434
struct gps_device_t *session)
435435
{
436436
int l1;
437+
int expected_len;
437438

438439
print_data(session->context, bu, len, pgn);
439440
GPSD_LOG(LOG_DATA, &session->context->errout,
440441
"pgn %6d(%3d):\n", pgn->pgn, session->driver.nmea2000.unit);
441442

442443
session->driver.nmea2000.sid[2] = bu[0];
443444
session->gpsdata.satellites_visible = (int)bu[2];
445+
if (MAXCHANNELS <= session->gpsdata.satellites_visible) {
446+
// Handle a CVE for overrunning skyview[]
447+
GPSD_LOG(LOG_WARN, &session->context->errout,
448+
"pgn %6d(%3d): Too many sats %d\n",
449+
pgn->pgn, session->driver.nmea2000.unit,
450+
session->gpsdata.satellites_visible);
451+
session->gpsdata.satellites_visible = MAXCHANNELS;
452+
}
453+
expected_len = 3 + (12 * session->gpsdata.satellites_visible);
454+
if (len != expected_len) {
455+
GPSD_LOG(LOG_WARN, &session->context->errout,
456+
"pgn %6d(%3d): wrong length %d s/b %d\n",
457+
pgn->pgn, session->driver.nmea2000.unit,
458+
len, expected_len);
459+
return 0;
460+
}
444461

445462
memset(session->gpsdata.skyview, '\0', sizeof(session->gpsdata.skyview));
446-
for (l1=0;l1<session->gpsdata.satellites_visible;l1++) {
447-
int svt;
448-
double azi, elev, snr;
449-
450-
elev = getles16(bu, 3+12*l1+1) * 1e-4 * RAD_2_DEG;
451-
azi = getleu16(bu, 3+12*l1+3) * 1e-4 * RAD_2_DEG;
452-
snr = getles16(bu, 3+12*l1+5) * 1e-2;
463+
for (l1 = 0; l1 < session->gpsdata.satellites_visible; l1++) {
464+
int offset = 3 + (12 * l1);
465+
double elev = getles16(bu, offset + 1) * 1e-4 * RAD_2_DEG;
466+
double azi = getleu16(bu, offset + 3) * 1e-4 * RAD_2_DEG;
467+
double snr = getles16(bu, offset + 5) * 1e-2;
453468

454-
svt = (int)(bu[3+12*l1+11] & 0x0f);
469+
int svt = (int)(bu[offset + 11] & 0x0f);
455470

456-
session->gpsdata.skyview[l1].elevation = (short) (round(elev));
457-
session->gpsdata.skyview[l1].azimuth = (short) (round(azi));
471+
session->gpsdata.skyview[l1].elevation = elev;
472+
session->gpsdata.skyview[l1].azimuth = azi;
458473
session->gpsdata.skyview[l1].ss = snr;
459-
session->gpsdata.skyview[l1].PRN = (short)bu[3+12*l1+0];
474+
session->gpsdata.skyview[l1].PRN = (int16_t)bu[offset];
460475
session->gpsdata.skyview[l1].used = false;
461-
if ((svt == 2) || (svt == 5)) {
476+
if ((2 == svt) ||
477+
(5 == svt)) {
462478
session->gpsdata.skyview[l1].used = true;
463479
}
464480
}
@@ -588,7 +604,7 @@ static gps_mask_t hnd_129029(unsigned char *bu, int len, PGN *pgn,
588604
struct gps_device_t *session)
589605
{
590606
gps_mask_t mask;
591-
uint64_t usecs; /* time in us */
607+
uint64_t usecs; // time in us
592608

593609
print_data(session->context, bu, len, pgn);
594610
GPSD_LOG(LOG_DATA, &session->context->errout,
@@ -675,7 +691,7 @@ static gps_mask_t hnd_129038(unsigned char *bu, int len, PGN *pgn,
675691
(unsigned int)ais_direction((unsigned int)getleu16(bu, 21), 1.0);
676692
ais->type1.turn = ais_turn_rate((int)getles16(bu, 23));
677693
ais->type1.status = (unsigned int) ((bu[25] >> 0) & 0x0f);
678-
ais->type1.maneuver = 0; /* Not transmitted ???? */
694+
ais->type1.maneuver = 0; // Not transmitted ????
679695
decode_ais_channel_info(bu, len, 163, session);
680696

681697
return(ONLINE_SET | AIS_SET);
@@ -730,8 +746,9 @@ static gps_mask_t hnd_129039(unsigned char *bu, int len, PGN *pgn,
730746

731747
/*
732748
* PGN 129040: AIS Class B Extended Position Report
749+
*
750+
* No test case for this message at the moment
733751
*/
734-
/* No test case for this message at the moment */
735752
static gps_mask_t hnd_129040(unsigned char *bu, int len, PGN *pgn,
736753
struct gps_device_t *session)
737754
{
@@ -781,8 +798,8 @@ static gps_mask_t hnd_129040(unsigned char *bu, int len, PGN *pgn,
781798
ais->type19.epfd = (unsigned int) ((bu[23] >> 4) & 0x0f);
782799
ais->type19.dte = (unsigned int) ((bu[52] >> 0) & 0x01);
783800
ais->type19.assigned = (bool) ((bu[52] >> 1) & 0x01);
784-
for (l=0;l<AIS_SHIPNAME_MAXLEN;l++) {
785-
ais->type19.shipname[l] = (char) bu[32+l];
801+
for (l = 0; l < AIS_SHIPNAME_MAXLEN; l++) {
802+
ais->type19.shipname[l] = (char)bu[32+l];
786803
}
787804
ais->type19.shipname[AIS_SHIPNAME_MAXLEN] = (char) 0;
788805
decode_ais_channel_info(bu, len, 422, session);
@@ -914,7 +931,7 @@ static gps_mask_t hnd_129794(unsigned char *bu, int len, PGN *pgn,
914931
ais->type5.draught = (unsigned int) (getleu16(bu, 51)/10);
915932
ais->type5.dte = (unsigned int) ((bu[73] >> 6) & 0x01);
916933

917-
for (l=0,cpy_stop=0;l<7;l++) {
934+
for (l = 0, cpy_stop = 0; l < 7; l++) {
918935
char next;
919936

920937
next = (char) bu[9+l];
@@ -929,7 +946,7 @@ static gps_mask_t hnd_129794(unsigned char *bu, int len, PGN *pgn,
929946
}
930947
ais->type5.callsign[7] = (char) 0;
931948

932-
for (l=0,cpy_stop=0;l<AIS_SHIPNAME_MAXLEN;l++) {
949+
for (l = 0, cpy_stop = 0; l < AIS_SHIPNAME_MAXLEN; l++) {
933950
char next;
934951

935952
next = (char) bu[16+l];
@@ -944,7 +961,7 @@ static gps_mask_t hnd_129794(unsigned char *bu, int len, PGN *pgn,
944961
}
945962
ais->type5.shipname[AIS_SHIPNAME_MAXLEN] = (char) 0;
946963

947-
for (l=0,cpy_stop=0;l<20;l++) {
964+
for (l = 0, cpy_stop = 0; l < 20; l++) {
948965
char next;
949966

950967
next = (char) bu[53+l];
@@ -978,7 +995,7 @@ static gps_mask_t hnd_129794(unsigned char *bu, int len, PGN *pgn,
978995
date2.tm_year+1900,
979996
ais->type5.hour,
980997
ais->type5.minute);
981-
#endif /* of #if NMEA2000_DEBUG_AIS */
998+
#endif // end of #if NMEA2000_DEBUG_AIS
982999
decode_ais_channel_info(bu, len, 592, session);
9831000
return(ONLINE_SET | AIS_SET);
9841001
}
@@ -988,8 +1005,9 @@ static gps_mask_t hnd_129794(unsigned char *bu, int len, PGN *pgn,
9881005

9891006
/*
9901007
* PGN 129798: AIS SAR Aircraft Position Report
1008+
*
1009+
* No test case for this message at the moment
9911010
*/
992-
/* No test case for this message at the moment */
9931011
static gps_mask_t hnd_129798(unsigned char *bu, int len, PGN *pgn,
9941012
struct gps_device_t *session)
9951013
{
@@ -1016,8 +1034,8 @@ static gps_mask_t hnd_129798(unsigned char *bu, int len, PGN *pgn,
10161034
ais->type9.alt = (unsigned int) (getleu64(bu, 21)/1000000);
10171035
ais->type9.regional = (unsigned int) ((bu[29] >> 0) & 0xff);
10181036
ais->type9.dte = (unsigned int) ((bu[30] >> 0) & 0x01);
1019-
/* ais->type9.spare = (bu[30] >> 1) & 0x7f; */
1020-
ais->type9.assigned = 0; /* Not transmitted ???? */
1037+
// ais->type9.spare = (bu[30] >> 1) & 0x7f;
1038+
ais->type9.assigned = 0; // Not transmitted ????
10211039
decode_ais_channel_info(bu, len, 163, session);
10221040

10231041
return(ONLINE_SET | AIS_SET);
@@ -1028,8 +1046,9 @@ static gps_mask_t hnd_129798(unsigned char *bu, int len, PGN *pgn,
10281046

10291047
/*
10301048
* PGN 129802: AIS Safety Related Broadcast Message
1049+
*
1050+
* No test case for this message at the moment
10311051
*/
1032-
/* No test case for this message at the moment */
10331052
static gps_mask_t hnd_129802(unsigned char *bu, int len, PGN *pgn,
10341053
struct gps_device_t *session)
10351054
{
@@ -1043,8 +1062,8 @@ static gps_mask_t hnd_129802(unsigned char *bu, int len, PGN *pgn,
10431062
if (decode_ais_header(session->context, bu, len, ais, 0x3fffffff) != 0) {
10441063
int l;
10451064

1046-
/* ais->type14.channel = (bu[ 5] >> 0) & 0x1f; */
1047-
for (l=0;l<36;l++) {
1065+
// ais->type14.channel = (bu[ 5] >> 0) & 0x1f;
1066+
for (l = 0; l < 36; l++) {
10481067
ais->type14.text[l] = (char) bu[6+l];
10491068
}
10501069
ais->type14.text[36] = (char) 0;
@@ -1079,7 +1098,7 @@ static gps_mask_t hnd_129809(unsigned char *bu, int len, PGN *pgn,
10791098
"NMEA2000: AIS message 24A from %09u stashed.\n",
10801099
ais->mmsi);
10811100

1082-
for (l=0;l<AIS_SHIPNAME_MAXLEN;l++) {
1101+
for (l = 0; l < AIS_SHIPNAME_MAXLEN; l++) {
10831102
ais->type24.shipname[l] = (char) bu[ 5+l];
10841103
saveptr->shipname[l] = (char) bu[ 5+l];
10851104
}
@@ -1119,12 +1138,12 @@ static gps_mask_t hnd_129810(unsigned char *bu, int len, PGN *pgn,
11191138

11201139
ais->type24.shiptype = (unsigned int) ((bu[ 5] >> 0) & 0xff);
11211140

1122-
for (l=0;l<7;l++) {
1141+
for (l = 0; l < 7; l++) {
11231142
ais->type24.vendorid[l] = (char) bu[ 6+l];
11241143
}
11251144
ais->type24.vendorid[7] = (char) 0;
11261145

1127-
for (l=0;l<7;l++) {
1146+
for (l = 0; l < 7; l++) {
11281147
ais->type24.callsign[l] = (char) bu[13+l];
11291148
}
11301149
ais->type24.callsign[7] = (char )0;
@@ -1158,7 +1177,7 @@ static gps_mask_t hnd_129810(unsigned char *bu, int len, PGN *pgn,
11581177
for (i = 0; i < MAX_TYPE24_INTERLEAVE; i++) {
11591178
if (session->driver.aivdm.context[0].type24_queue.ships[i].mmsi ==
11601179
ais->mmsi) {
1161-
for (l=0;l<AIS_SHIPNAME_MAXLEN;l++) {
1180+
for (l = 0; l < AIS_SHIPNAME_MAXLEN; l++) {
11621181
ais->type24.shipname[l] =
11631182
(char)(session->driver.aivdm.context[0].type24_queue.ships[i].shipname[l]);
11641183
}
@@ -1566,7 +1585,7 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
15661585
frame->can_id & 0x1ffffff);
15671586
if ((frame->can_dlc & 0x0f) > 0) {
15681587
int l1;
1569-
for(l1=0;l1<(frame->can_dlc & 0x0f);l1++) {
1588+
for(l1 = 0; l1 < (frame->can_dlc & 0x0f); l1++) {
15701589
(void)fprintf(logFile, "%02x", frame->data[l1]);
15711590
}
15721591
}
@@ -1591,8 +1610,8 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
15911610
if (!session->driver.nmea2000.unit_valid) {
15921611
unsigned int l1, l2;
15931612

1594-
for (l1=0;l1<NMEA2000_NETS;l1++) {
1595-
for (l2=0;l2<NMEA2000_UNITS;l2++) {
1613+
for (l1 = 0; l1 < NMEA2000_NETS; l1++) {
1614+
for (l2 = 0; l2 < NMEA2000_UNITS; l2++) {
15961615
if (session == nmea2000_units[l1][l2]) {
15971616
session->driver.nmea2000.unit = l2;
15981617
session->driver.nmea2000.unit_valid = true;
@@ -1641,7 +1660,7 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
16411660
"pgn %6d:%s \n", work->pgn, work->name);
16421661
session->driver.nmea2000.workpgn = (void *) work;
16431662
session->lexer.outbuflen = frame->can_dlc & 0x0f;
1644-
for (l2=0;l2<session->lexer.outbuflen;l2++) {
1663+
for (l2 = 0; l2 < session->lexer.outbuflen; l2++) {
16451664
session->lexer.outbuffer[l2]= frame->data[l2];
16461665
}
16471666
} else if ((frame->data[0] & 0x1f) == 0) {
@@ -1659,7 +1678,7 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
16591678
#endif /* of #if NMEA2000_FAST_DEBUG */
16601679
session->lexer.inbuflen = 0;
16611680
session->driver.nmea2000.idx += 1;
1662-
for (l2=2;l2<8;l2++) {
1681+
for (l2 = 2; l2 < 8; l2++) {
16631682
session->lexer.inbuffer[session->lexer.inbuflen++] =
16641683
frame->data[l2];
16651684
}
@@ -1668,7 +1687,7 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
16681687
} else if (frame->data[0] == session->driver.nmea2000.idx) {
16691688
unsigned int l2;
16701689

1671-
for (l2=1;l2<8;l2++) {
1690+
for (l2 = 1; l2 < 8; l2++) {
16721691
if (session->driver.nmea2000.fast_packet_len >
16731692
session->lexer.inbuflen) {
16741693
session->lexer.inbuffer[session->lexer.inbuflen++] =
@@ -1689,7 +1708,7 @@ static void find_pgn(struct can_frame *frame, struct gps_device_t *session)
16891708
session->driver.nmea2000.workpgn = (void *) work;
16901709
session->lexer.outbuflen =
16911710
session->driver.nmea2000.fast_packet_len;
1692-
for(l2 = 0;l2 < (unsigned int)session->lexer.outbuflen;
1711+
for(l2 = 0; l2 < (unsigned int)session->lexer.outbuflen;
16931712
l2++) {
16941713
session->lexer.outbuffer[l2] =
16951714
session->lexer.inbuffer[l2];
@@ -1792,7 +1811,7 @@ int nmea2000_open(struct gps_device_t *session)
17921811
(void)strlcpy(interface_name, session->gpsdata.dev.path + 11,
17931812
sizeof(interface_name));
17941813
unit_ptr = NULL;
1795-
for (l=0;l<strnlen(interface_name,sizeof(interface_name));l++) {
1814+
for (l = 0; l < strnlen(interface_name, sizeof(interface_name)); l++) {
17961815
if (interface_name[l] == ':') {
17971816
unit_ptr = &interface_name[l+1];
17981817
interface_name[l] = 0;
@@ -1909,7 +1928,7 @@ int nmea2000_open(struct gps_device_t *session)
19091928
interface_name,
19101929
MIN(sizeof(can_interface_name[0]), sizeof(interface_name)));
19111930
session->driver.nmea2000.unit_valid = false;
1912-
for (l=0;l<NMEA2000_UNITS;l++) {
1931+
for (l = 0; l < NMEA2000_UNITS; l++) {
19131932
nmea2000_units[can_net][l] = NULL;
19141933
}
19151934
}
@@ -1933,8 +1952,8 @@ void nmea2000_close(struct gps_device_t *session)
19331952
if (session->driver.nmea2000.unit_valid) {
19341953
unsigned int l1, l2;
19351954

1936-
for (l1=0;l1<NMEA2000_NETS;l1++) {
1937-
for (l2=0;l2<NMEA2000_UNITS;l2++) {
1955+
for (l1 = 0; l1 < NMEA2000_NETS; l1++) {
1956+
for (l2 = 0; l2 < NMEA2000_UNITS; l2++) {
19381957
if (session == nmea2000_units[l1][l2]) {
19391958
session->driver.nmea2000.unit_valid = false;
19401959
session->driver.nmea2000.unit = 0;

0 commit comments

Comments
 (0)