From 27030b3e54911727142d71c60c93ea57699fa592 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Mon, 11 Mar 2024 22:47:15 +0100 Subject: [PATCH] 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 --- asc2log.c | 2 +- candump.c | 4 +- cangen.c | 4 +- canlogserver.c | 2 +- canplayer.c | 2 +- lib.c | 100 ++++++++++++++++++++++++++++++++++++++++--------- lib.h | 4 +- log2long.c | 4 +- 8 files changed, 94 insertions(+), 28 deletions(-) diff --git a/asc2log.c b/asc2log.c index fbbb01b..5ffc1be 100644 --- a/asc2log.c +++ b/asc2log.c @@ -82,7 +82,7 @@ void prframe(FILE *file, struct timeval *tv, int dev, struct canfd_frame *cf, ch else 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); } diff --git a/candump.c b/candump.c index 87958cd..2c57b8d 100644 --- a/candump.c +++ b/candump.c @@ -837,7 +837,7 @@ int main(int argc, char **argv) alen += sprintf(afrbuf + alen, "%*s ", 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 */ @@ -876,7 +876,7 @@ int main(int argc, char **argv) } 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)) { alen += sprintf(afrbuf + alen, "\n\t"); diff --git a/cangen.c b/cangen.c index 0e5ec8d..4e27261 100644 --- a/cangen.c +++ b/cangen.c @@ -1009,9 +1009,9 @@ int main(int argc, char **argv) printf(" %s ", argv[optind]); if (verbose > 1) - sprint_long_canframe(afrbuf, &cu, view); + snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, view); else - sprint_canframe(afrbuf, &cu, 1); + snprintf_canframe(afrbuf, sizeof(afrbuf), &cu, 1); printf("%s\n", afrbuf); } diff --git a/canlogserver.c b/canlogserver.c index ca900ef..1921e23 100644 --- a/canlogserver.c +++ b/canlogserver.c @@ -439,7 +439,7 @@ int main(int argc, char **argv) sprintf(afrbuf, "(%llu.%06llu) %*s ", (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"); if (write(accsocket, afrbuf, strlen(afrbuf)) < 0) { diff --git a/canplayer.c b/canplayer.c index a38a82a..dfd1919 100644 --- a/canplayer.c +++ b/canplayer.c @@ -513,7 +513,7 @@ int main(int argc, char **argv) if (verbose) { 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); } diff --git a/lib.c b/lib.c index bd8d3cf..1c2ec0c 100644 --- a/lib.c +++ b/lib.c @@ -308,7 +308,7 @@ int parse_canframe(char *cs, cu_t *cu) 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 */ @@ -316,10 +316,22 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) int i, offset; int len; + /* ensure space for string termination */ + if (size < 1) + return size; + /* handle CAN XL frames */ if (cu->xl.flags & CANXL_XLF) { 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 */ offset = sprintf(buf, "%02X%03X#%02X:%02X:%08X#", (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 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) { put_eff_id(buf, cu->fd.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); buf[8] = '#'; @@ -411,48 +432,60 @@ int sprint_canframe(char *buf, cu_t *cu, int sep) 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 */ unsigned char is_canfd = cu->fd.flags; - int i, j, dlen, offset; + int i, j, dlen, offset, maxsize; int len; - /* initialize space for CAN-ID and length information */ - memset(buf, ' ', 15); + /* ensure space for string termination */ + if (size < 1) + return size; /* handle CAN XL frames */ if (cu->xl.flags & CANXL_XLF) { 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) { + memset(buf, ' ', 5); put_sff_id(buf + 5, cu->xl.prio & CANXL_PRIO_MASK); - offset = 9; + offset = 8; } else { put_sff_id(buf, cu->xl.prio & CANXL_PRIO_MASK); - offset = 4; + offset = 3; } /* 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, (canid_t)(cu->xl.prio & CANXL_VCID_MASK) >> CANXL_VCID_OFFSET, cu->xl.flags, cu->xl.sdt, cu->xl.af); - /* data - crop to CANFD_MAX_DLEN */ - if (len > CANFD_MAX_DLEN) - len = CANFD_MAX_DLEN; - - for (i = 0; i < len; i++) { + for (i = 0; i < dlen; i++) { put_hex_byte(buf + offset, cu->xl.data[i]); offset += 2; - if (i + 1 < len) + if (i + 1 < dlen) buf[offset++] = ' '; } /* indicate cropped output */ - if (cu->xl.len > len) + if (cu->xl.len > dlen) offset += sprintf(buf + offset, " ..."); buf[offset] = 0; @@ -466,6 +499,39 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) else 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) { put_eff_id(buf, cu->cc.can_id & (CAN_ERR_MASK | CAN_ERR_FLAG)); offset = 10; @@ -515,7 +581,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) offset += 5; if (view & CANLIB_VIEW_BINARY) { - dlen = 9; /* _10101010 */ + /* _10101010 - dlen = 9, see above */ if (view & CANLIB_VIEW_SWAP) { for (i = len - 1; i >= 0; i--) { buf[offset++] = (i == len - 1) ? ' ' : SWAP_DELIMITER; @@ -530,7 +596,7 @@ int sprint_long_canframe(char *buf, cu_t *cu, int view) } } } else { - dlen = 3; /* _AA */ + /* _AA - dlen = 3, see above */ if (view & CANLIB_VIEW_SWAP) { for (i = len - 1; i >= 0; i--) { if (i == len - 1) diff --git a/lib.h b/lib.h index 23514c7..1ab0324 100644 --- a/lib.h +++ b/lib.h @@ -178,7 +178,7 @@ int parse_canframe(char *cs, cu_t *cu); * - 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. * 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 '`' -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. * diff --git a/log2long.c b/log2long.c index 731d29a..301f201 100644 --- a/log2long.c +++ b/log2long.c @@ -94,8 +94,8 @@ int main(void) } /* with ASCII output */ - sprint_long_canframe(afrbuf, &cu, - (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); + snprintf_long_canframe(afrbuf, sizeof(afrbuf), &cu, + (CANLIB_VIEW_INDENT_SFF | CANLIB_VIEW_ASCII)); printf("%s %s %s\n", timestamp, device, afrbuf); }