lib: make sprint_canframe the buffer size aware snprintf_canframe

Make sure the library functions to convert CAN frames into ASCII
represenation do not exceed the given buffer size. This also applies
to the long CAN frame output library function.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
pull/504/head
Oliver Hartkopp 2024-03-11 22:47:15 +01:00
parent 8e131401c1
commit 27030b3e54
8 changed files with 94 additions and 28 deletions

View File

@ -82,7 +82,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch
else else
fprintf(file, "canX "); fprintf(file, "canX ");
sprint_canframe(abuf, (cu_t *)cf, 0); snprintf_canframe(abuf, sizeof(abuf), (cu_t *)cf, 0);
fprintf(file, "%s%s", abuf, extra_info); fprintf(file, "%s%s", abuf, extra_info);
} }

View File

@ -837,7 +837,7 @@ int main(int argc, char **argv)
alen += sprintf(afrbuf + alen, "%*s ", alen += sprintf(afrbuf + alen, "%*s ",
max_devname_len, devname[idx]); max_devname_len, devname[idx]);
alen += sprint_canframe(afrbuf + alen, &cu, 0); alen += snprintf_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, 0);
} }
/* write CAN frame in log file style to logfile */ /* write CAN frame in log file style to logfile */
@ -876,7 +876,7 @@ int main(int argc, char **argv)
} }
alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : ""); alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : "");
alen += sprint_long_canframe(afrbuf + alen, &cu, view); alen += snprintf_long_canframe(afrbuf + alen, sizeof(afrbuf) - alen, &cu, view);
if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) { if ((view & CANLIB_VIEW_ERROR) && (cu.fd.can_id & CAN_ERR_FLAG)) {
alen += sprintf(afrbuf + alen, "\n\t"); alen += sprintf(afrbuf + alen, "\n\t");

View File

@ -1009,9 +1009,9 @@ int main(int argc, char **argv)
printf(" %s ", argv[optind]); printf(" %s ", argv[optind]);
if (verbose > 1) if (verbose > 1)
sprint_long_canframe(afrbuf, &cu, view); snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, view);
else else
sprint_canframe(afrbuf, &cu, 1); snprintf_canframe(afrbuf, sizeof(afrbuf), &cu, 1);
printf("%s\n", afrbuf); printf("%s\n", afrbuf);
} }

View File

@ -439,7 +439,7 @@ int main(int argc, char **argv)
sprintf(afrbuf, "(%llu.%06llu) %*s ", sprintf(afrbuf, "(%llu.%06llu) %*s ",
(unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]); (unsigned long long)tv.tv_sec, (unsigned long long)tv.tv_usec, max_devname_len, devname[idx]);
sprint_canframe(afrbuf+strlen(afrbuf), &cu, 0); snprintf_canframe(afrbuf + strlen(afrbuf), sizeof(afrbuf) - strlen(afrbuf), &cu, 0);
strcat(afrbuf, "\n"); strcat(afrbuf, "\n");
if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) { if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) {

View File

@ -513,7 +513,7 @@ int main(int argc, char **argv)
if (verbose) { if (verbose) {
printf("%s (%s) ", get_txname(device), device); printf("%s (%s) ", get_txname(device), device);
sprint_long_canframe(afrbuf, &cu, CANLIB_VIEW_INDENT_SFF); snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, CANLIB_VIEW_INDENT_SFF);
printf("%s\n", afrbuf); printf("%s\n", afrbuf);
} }

100
lib.c
View File

@ -308,7 +308,7 @@ int parse_canframe(char *cs, cu_t *cu)
return mtu; return mtu;
} }
int sprint_canframe(char *buf, cu_t *cu, int sep) int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
{ {
/* documentation see lib.h */ /* documentation see lib.h */
@ -316,10 +316,22 @@ int sprint_canframe(char *buf, cu_t *cu, int sep)
int i, offset; int i, offset;
int len; int len;
/* ensure space for string termination */
if (size < 1)
return size;
/* handle CAN XL frames */ /* handle CAN XL frames */
if (cu->xl.flags & CANXL_XLF) { if (cu->xl.flags & CANXL_XLF) {
len = cu->xl.len; len = cu->xl.len;
/* check if the CAN frame fits into the provided buffer */
if (sizeof("00123#11:22:12345678#") + 2 * len + (sep ? len : 0) > size - 1) {
/* mark buffer overflow in output */
memset(buf, '-', size - 1);
buf[size - 1] = 0;
return size;
}
/* print prio and CAN XL header content */ /* print prio and CAN XL header content */
offset = sprintf(buf, "%02X%03X#%02X:%02X:%08X#", offset = sprintf(buf, "%02X%03X#%02X:%02X:%08X#",
(canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET,
@ -345,6 +357,15 @@ int sprint_canframe(char *buf, cu_t *cu, int sep)
else else
len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len;
/* check if the CAN frame fits into the provided buffer */
if (sizeof("12345678#_F") + 2 * len + (sep ? len : 0) + \
(cu->fd.can_id & CAN_RTR_FLAG ? 2 : 0) > size - 1) {
/* mark buffer overflow in output */
memset(buf, '-', size - 1);
buf[size - 1] = 0;
return size;
}
if (cu->fd.can_id & CAN_ERR_FLAG) { if (cu->fd.can_id & CAN_ERR_FLAG) {
put_eff_id(buf, cu->fd.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); put_eff_id(buf, cu->fd.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG));
buf[8] = '#'; buf[8] = '#';
@ -411,48 +432,60 @@ int sprint_canframe(char *buf, cu_t *cu, int sep)
return offset; return offset;
} }
int sprint_long_canframe(char *buf, cu_t *cu, int view) int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view)
{ {
/* documentation see lib.h */ /* documentation see lib.h */
unsigned char is_canfd = cu->fd.flags; unsigned char is_canfd = cu->fd.flags;
int i, j, dlen, offset; int i, j, dlen, offset, maxsize;
int len; int len;
/* initialize space for CAN-ID and length information */ /* ensure space for string termination */
memset(buf, ' ', 15); if (size < 1)
return size;
/* handle CAN XL frames */ /* handle CAN XL frames */
if (cu->xl.flags & CANXL_XLF) { if (cu->xl.flags & CANXL_XLF) {
len = cu->xl.len; len = cu->xl.len;
/* crop to CANFD_MAX_DLEN */
if (len > CANFD_MAX_DLEN)
dlen = CANFD_MAX_DLEN;
else
dlen = len;
/* check if the CAN frame fits into the provided buffer */
if (sizeof(".....123 [2048] (00|11:22:12345678) ...") + 3 * dlen > size - 1) {
/* mark buffer overflow in output */
memset(buf, '-', size - 1);
buf[size - 1] = 0;
return size;
}
if (view & CANLIB_VIEW_INDENT_SFF) { if (view & CANLIB_VIEW_INDENT_SFF) {
memset(buf, ' ', 5);
put_sff_id(buf + 5, cu->xl.prio & CANXL_PRIO_MASK); put_sff_id(buf + 5, cu->xl.prio & CANXL_PRIO_MASK);
offset = 9; offset = 8;
} else { } else {
put_sff_id(buf, cu->xl.prio & CANXL_PRIO_MASK); put_sff_id(buf, cu->xl.prio & CANXL_PRIO_MASK);
offset = 4; offset = 3;
} }
/* print prio and CAN XL header content */ /* print prio and CAN XL header content */
offset += sprintf(buf + offset, "[%04d] (%02X|%02X:%02X:%08X) ", offset += sprintf(buf + offset, " [%04d] (%02X|%02X:%02X:%08X) ",
len, len,
(canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET,
cu->xl.flags, cu->xl.sdt, cu->xl.af); cu->xl.flags, cu->xl.sdt, cu->xl.af);
/* data - crop to CANFD_MAX_DLEN */ for (i = 0; i < dlen; i++) {
if (len > CANFD_MAX_DLEN)
len = CANFD_MAX_DLEN;
for (i = 0; i < len; i++) {
put_hex_byte(buf + offset, cu->xl.data[i]); put_hex_byte(buf + offset, cu->xl.data[i]);
offset += 2; offset += 2;
if (i + 1 < len) if (i + 1 < dlen)
buf[offset++] = ' '; buf[offset++] = ' ';
} }
/* indicate cropped output */ /* indicate cropped output */
if (cu->xl.len > len) if (cu->xl.len > dlen)
offset += sprintf(buf + offset, " ..."); offset += sprintf(buf + offset, " ...");
buf[offset] = 0; buf[offset] = 0;
@ -466,6 +499,39 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view)
else else
len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len; len = (cu->fd.len > CAN_MAX_DLEN) ? CAN_MAX_DLEN : cu->fd.len;
/* check if the CAN frame fits into the provided buffer */
maxsize = sizeof("12345678 [12] ");
if (view & CANLIB_VIEW_BINARY)
dlen = 9; /* _10101010 */
else
dlen = 3; /* _AA */
if (cu->fd.can_id & CAN_RTR_FLAG) {
maxsize += sizeof(" remote request");
} else {
maxsize += len * dlen;
if (len <= CAN_MAX_DLEN) {
if (cu->fd.can_id & CAN_ERR_FLAG) {
maxsize += sizeof(" ERRORFRAME");
maxsize += (8 - len) * dlen;
} else if (view & CANLIB_VIEW_ASCII) {
maxsize += sizeof(" 'a.b.CDEF'");
maxsize += (8 - len) * dlen;
}
}
}
if (maxsize > size - 1) {
/* mark buffer overflow in output */
memset(buf, '-', size - 1);
buf[size - 1] = 0;
return size;
}
/* initialize space for CAN-ID and length information */
memset(buf, ' ', 15);
if (cu->cc.can_id & CAN_ERR_FLAG) { if (cu->cc.can_id & CAN_ERR_FLAG) {
put_eff_id(buf, cu->cc.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); put_eff_id(buf, cu->cc.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG));
offset = 10; offset = 10;
@ -515,7 +581,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view)
offset += 5; offset += 5;
if (view & CANLIB_VIEW_BINARY) { if (view & CANLIB_VIEW_BINARY) {
dlen = 9; /* _10101010 */ /* _10101010 - dlen = 9, see above */
if (view & CANLIB_VIEW_SWAP) { if (view & CANLIB_VIEW_SWAP) {
for (i = len - 1; i >= 0; i--) { for (i = len - 1; i >= 0; i--) {
buf[offset++] = (i == len - 1) ? ' ' : SWAP_DELIMITER; buf[offset++] = (i == len - 1) ? ' ' : SWAP_DELIMITER;
@ -530,7 +596,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view)
} }
} }
} else { } else {
dlen = 3; /* _AA */ /* _AA - dlen = 3, see above */
if (view & CANLIB_VIEW_SWAP) { if (view & CANLIB_VIEW_SWAP) {
for (i = len - 1; i >= 0; i--) { for (i = len - 1; i >= 0; i--) {
if (i == len - 1) if (i == len - 1)

4
lib.h
View File

@ -178,7 +178,7 @@ int parse_canframe(char *cs, cu_t *cu);
* - CAN FD frames do not have a RTR bit * - CAN FD frames do not have a RTR bit
*/ */
int sprint_canframe(char *buf , cu_t *cu, int sep); int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
/* /*
* Creates a CAN frame hexadecimal output in compact format. * Creates a CAN frame hexadecimal output in compact format.
* The CAN data[] is separated by '.' when sep != 0. * The CAN data[] is separated by '.' when sep != 0.
@ -211,7 +211,7 @@ int sprint_canframe(char *buf , cu_t *cu, int sep);
#define SWAP_DELIMITER '`' #define SWAP_DELIMITER '`'
int sprint_long_canframe(char *buf , cu_t *cu, int view); int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view);
/* /*
* Creates a CAN frame hexadecimal output in user readable format. * Creates a CAN frame hexadecimal output in user readable format.
* *

View File

@ -94,8 +94,8 @@ int main(void)
} }
/* with ASCII output */ /* with ASCII output */
sprint_long_canframe(afrbuf, &cu, snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu,
(CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII));
printf("%s %s %s\n", timestamp, device, afrbuf); printf("%s %s %s\n", timestamp, device, afrbuf);
} }