Fix buffer overflows and track successful parsing

This commit is contained in:
PaulStoffregen 2016-03-09 03:19:55 -08:00
commit 098adc6912

View file

@ -12,7 +12,7 @@ void print_data(const char *name, const unsigned char *data, int len)
printf("\n"); printf("\n");
} }
static void packet_primary_data(const unsigned char *data) static int packet_primary_data(const unsigned char *data)
{ {
//current_position.x = (float)((int16_t)((data[13] << 8) | data[12])) / 10.0f; //current_position.x = (float)((int16_t)((data[13] << 8) | data[12])) / 10.0f;
//current_position.y = (float)((int16_t)((data[15] << 8) | data[14])) / 10.0f; //current_position.y = (float)((int16_t)((data[15] << 8) | data[14])) / 10.0f;
@ -36,9 +36,10 @@ static void packet_primary_data(const unsigned char *data)
current_orientation.z current_orientation.z
); );
#endif #endif
return 1;
} }
static void packet_magnetic_cal(const unsigned char *data) static int packet_magnetic_cal(const unsigned char *data)
{ {
int16_t id, x, y, z; int16_t id, x, y, z;
magdata_t *cal; magdata_t *cal;
@ -54,15 +55,18 @@ static void packet_magnetic_cal(const unsigned char *data)
cal->x = (float)x / 10.0f; cal->x = (float)x / 10.0f;
cal->y = (float)y / 10.0f; cal->y = (float)y / 10.0f;
cal->z = (float)z / 10.0f; cal->z = (float)z / 10.0f;
return 1;
} else if (id == 2) { } else if (id == 2) {
soft_iron[0] = (float)x / 1000.0f; soft_iron[0] = (float)x / 1000.0f;
soft_iron[4] = (float)y / 1000.0f; soft_iron[4] = (float)y / 1000.0f;
soft_iron[8] = (float)z / 1000.0f; soft_iron[8] = (float)z / 1000.0f;
return 1;
} else if (id == 3) { } else if (id == 3) {
soft_iron[1] = soft_iron[3] = (float)x / 1000.0f; // finvW[X][Y] soft_iron[1] = soft_iron[3] = (float)x / 1000.0f; // finvW[X][Y]
soft_iron[2] = soft_iron[6] = (float)y / 1000.0f; // finvW[X][Z] soft_iron[2] = soft_iron[6] = (float)y / 1000.0f; // finvW[X][Z]
soft_iron[5] = soft_iron[7] = (float)z / 1000.0f; // finvW[Y][Z] soft_iron[5] = soft_iron[7] = (float)z / 1000.0f; // finvW[Y][Z]
cal->valid = 1; cal->valid = 1;
return 1;
} else if (id >= 10 && id < MAGBUFFSIZE+10) { } else if (id >= 10 && id < MAGBUFFSIZE+10) {
newx = (float)x / 10.0f; newx = (float)x / 10.0f;
newy = (float)y / 10.0f; newy = (float)y / 10.0f;
@ -75,23 +79,25 @@ static void packet_magnetic_cal(const unsigned char *data)
cal->valid = 1; cal->valid = 1;
printf("mag cal, id=%3d: %5d %5d %5d\n", id, x, y, z); printf("mag cal, id=%3d: %5d %5d %5d\n", id, x, y, z);
} }
return 1;
} }
return 0;
} }
static void packet(const unsigned char *data, int len) static int packet(const unsigned char *data, int len)
{ {
if (len <= 0) return; if (len <= 0) return 0;
//print_data("packet", data, len); //print_data("packet", data, len);
if (data[0] == 1 && len == 34) { if (data[0] == 1 && len == 34) {
packet_primary_data(data); return packet_primary_data(data);
} else if (data[0] == 6 && len == 14) { } else if (data[0] == 6 && len == 14) {
packet_magnetic_cal(data); return packet_magnetic_cal(data);
} }
// TODO: actually do something with the arriving data... return 0;
} }
static void packet_encoded(const unsigned char *data, int len) static int packet_encoded(const unsigned char *data, int len)
{ {
const unsigned char *p; const unsigned char *p;
unsigned char buf[256]; unsigned char buf[256];
@ -100,55 +106,62 @@ static void packet_encoded(const unsigned char *data, int len)
//printf("packet_encoded, len = %d\n", len); //printf("packet_encoded, len = %d\n", len);
p = memchr(data, 0x7D, len); p = memchr(data, 0x7D, len);
if (p == NULL) { if (p == NULL) {
packet(data, len); return packet(data, len);
} else { } else {
//printf("** decoding necessary\n"); //printf("** decoding necessary\n");
while (1) { while (1) {
copylen = p - data; copylen = p - data;
if (copylen > 0) { if (copylen > 0) {
//printf(" copylen = %d\n", copylen); //printf(" copylen = %d\n", copylen);
// TODO: overflow check if (buflen + copylen > sizeof(buf)) return 0;
memcpy(buf+buflen, data, copylen); memcpy(buf+buflen, data, copylen);
buflen += copylen; buflen += copylen;
data += copylen; data += copylen;
len -= copylen; len -= copylen;
} }
// TODO: overflow check if (buflen + 1 > sizeof(buf)) return 0;
buf[buflen++] = (p[1] == 0x5E) ? 0x7E : 0x7D; buf[buflen++] = (p[1] == 0x5E) ? 0x7E : 0x7D;
data += 2; data += 2;
len -= 2; len -= 2;
if (len <= 0) break; if (len <= 0) break;
p = memchr(data, 0x7D, len); p = memchr(data, 0x7D, len);
if (p == NULL) { if (p == NULL) {
// TODO: overflow check if (buflen + len > sizeof(buf)) return 0;
memcpy(buf+buflen, data, len); memcpy(buf+buflen, data, len);
buflen += len; buflen += len;
break; break;
} }
} }
//printf("** decoded to %d\n", buflen); //printf("** decoded to %d\n", buflen);
packet(buf, buflen); return packet(buf, buflen);
} }
} }
static void newdata(const unsigned char *data, int len) static int packet_parse(const unsigned char *data, int len)
{ {
static unsigned char packetbuf[256]; static unsigned char packetbuf[256];
static unsigned int packetlen=0; static unsigned int packetlen=0;
const unsigned char *p; const unsigned char *p;
int copylen; int copylen;
int ret=0;
//print_data("newdata", data, len); print_data("newdata", data, len);
while (len > 0) { while (len > 0) {
p = memchr(data, 0x7E, len); p = memchr(data, 0x7E, len);
if (p == NULL) { if (p == NULL) {
// TODO: overflow check if (packetlen + len > sizeof(packetbuf)) {
packetlen = 0;
return 0; // would overflow buffer
}
memcpy(packetbuf+packetlen, data, len); memcpy(packetbuf+packetlen, data, len);
packetlen += len; packetlen += len;
len = 0; len = 0;
} else if (p > data) { } else if (p > data) {
copylen = p - data; copylen = p - data;
// TODO: overflow check if (packetlen + copylen > sizeof(packetbuf)) {
packetlen = 0;
return 0; // would overflow buffer
}
memcpy(packetbuf+packetlen, data, copylen); memcpy(packetbuf+packetlen, data, copylen);
packet_encoded(packetbuf, packetlen+copylen); packet_encoded(packetbuf, packetlen+copylen);
packetlen = 0; packetlen = 0;
@ -156,15 +169,23 @@ static void newdata(const unsigned char *data, int len)
len -= copylen + 1; len -= copylen + 1;
} else { } else {
if (packetlen > 0) { if (packetlen > 0) {
packet_encoded(packetbuf, packetlen); if (packet_encoded(packetbuf, packetlen)) ret = 1;
packetlen = 0; packetlen = 0;
} }
data++; data++;
len--; len--;
} }
} }
return ret;
} }
static void newdata(const unsigned char *data, int len)
{
packet_parse(data, len);
// TODO: ascii parse
}
#if defined(LINUX) || defined(MACOSX) #if defined(LINUX) || defined(MACOSX)
static int portfd=-1; static int portfd=-1;