summaryrefslogtreecommitdiff
path: root/libgps_sock.c
diff options
context:
space:
mode:
authorGary E. Miller <gem@rellim.com>2018-07-14 12:17:35 -0700
committerGary E. Miller <gem@rellim.com>2018-07-14 12:17:35 -0700
commit6bba8b329fc7687b15863d30471d5af402467802 (patch)
tree10975c312ee76bf58c4f66b6997e07c4f5e5e4c3 /libgps_sock.c
parent692427a17aeb54d69826def759cc1f1da605ba33 (diff)
downloadgpsd-6bba8b329fc7687b15863d30471d5af402467802.tar.gz
gps_read(): fix some nasty buffer overruns and corruptions.
Now pass an optional message buffer to gps_read(). Finally the JSON display in cgps works. Thanks to Virgin Orbit for their support fixing this bug.
Diffstat (limited to 'libgps_sock.c')
-rw-r--r--libgps_sock.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/libgps_sock.c b/libgps_sock.c
index c4303da5..63635234 100644
--- a/libgps_sock.c
+++ b/libgps_sock.c
@@ -178,23 +178,27 @@ int gps_sock_close(struct gps_data_t *gpsdata)
#endif
}
-int gps_sock_read(struct gps_data_t *gpsdata)
+int gps_sock_read(struct gps_data_t *gpsdata, char *message, int message_len)
/* wait for and read data being streamed from the daemon */
{
char *eol;
ssize_t response_length;
int status = -1;
+ errno = 0;
gpsdata->set &= ~PACKET_SET;
+
+ /* scan to find end of message (\n), or end of buffer */
for (eol = PRIVATE(gpsdata)->buffer;
- *eol != '\n' && eol < PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting; eol++)
- continue;
- if (*eol != '\n')
- eol = NULL;
+ eol < (PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting);
+ eol++) {
+ if ('\n' == *eol)
+ break;
+ }
- errno = 0;
+ if (*eol != '\n') {
+ /* no full message found, try to fill buffer */
- if (eol == NULL) {
#ifndef USE_QT
/* read data: return -1 if no data waiting or buffered, 0 otherwise */
status = (int)recv(gpsdata->gps_fd,
@@ -210,11 +214,13 @@ int gps_sock_read(struct gps_data_t *gpsdata)
#ifdef HAVE_WINSOCK2_H
int wserr = WSAGetLastError();
#endif /* HAVE_WINSOCK2_H */
+
/* if we just received data from the socket, it's in the buffer */
if (status > -1)
PRIVATE(gpsdata)->waiting += status;
- /* buffer is empty - implies no data was read */
+
if (PRIVATE(gpsdata)->waiting == 0) {
+ /* buffer is empty - implies no data was read */
/*
* If we received 0 bytes, other side of socket is closing.
* Return -1 as end-of-data indication.
@@ -237,23 +243,37 @@ int gps_sock_read(struct gps_data_t *gpsdata)
else
return -1;
}
- /* there's buffered data waiting to be returned */
+
+ /* there's new buffered data waiting, check for full message */
for (eol = PRIVATE(gpsdata)->buffer;
- *eol != '\n' && eol < PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting; eol++)
- continue;
+ eol < (PRIVATE(gpsdata)->buffer + PRIVATE(gpsdata)->waiting);
+ eol++) {
+ if ('\n' == *eol)
+ break;
+ }
if (*eol != '\n')
- eol = NULL;
- if (eol == NULL)
+ /* still no full message, give up for now */
return 0;
}
- assert(eol != NULL);
+ /* eol now points to trailing \n in a full message */
*eol = '\0';
- response_length = eol - PRIVATE(gpsdata)->buffer + 1;
+ if (NULL != message) {
+ strlcpy(message, PRIVATE(gpsdata)->buffer, message_len);
+ }
gpsdata->online = timestamp();
+ /* unpack the JSON message */
status = gps_unpack(PRIVATE(gpsdata)->buffer, gpsdata);
- memmove(PRIVATE(gpsdata)->buffer,
- PRIVATE(gpsdata)->buffer + response_length, PRIVATE(gpsdata)->waiting - response_length);
+
+ response_length = eol - PRIVATE(gpsdata)->buffer + 1;
+ if (0 == (PRIVATE(gpsdata)->waiting - response_length)) {
+ /* no waiting data, clear the buffer, just in case */
+ *PRIVATE(gpsdata)->buffer = '\0';
+ } else {
+ memmove(PRIVATE(gpsdata)->buffer,
+ PRIVATE(gpsdata)->buffer + response_length,
+ PRIVATE(gpsdata)->waiting - response_length);
+ }
PRIVATE(gpsdata)->waiting -= response_length;
gpsdata->set |= PACKET_SET;
@@ -292,6 +312,7 @@ int gps_unpack(char *buf, struct gps_data_t *gpsdata)
const char *gps_sock_data(const struct gps_data_t *gpsdata)
/* return the contents of the client data buffer */
{
+ /* no length data, so pretty useless... */
return PRIVATE(gpsdata)->buffer;
}
@@ -384,7 +405,7 @@ int gps_sock_mainloop(struct gps_data_t *gpsdata, int timeout,
if (!gps_waiting(gpsdata, timeout)) {
return -1;
} else {
- int status = gps_read(gpsdata);
+ int status = gps_read(gpsdata, NULL, 0);
if (status == -1)
return -1;