Skip to content

Commit

Permalink
channel.c: track length of buffer when buidling xml
Browse files Browse the repository at this point in the history
As we are building up the xml, keep track of the length of the
(remaining) buffer, and check it at the end to make sure we didn't
overflow.

This does change the max length of the channel xml description from MAX_size_t
to MAX_ssize_t.  Worse case, that is from 64k to 32k. The C spec defines the
minimum size_t to 16-bits.  Nominally, on most modern compilers (where size_t
is 32-bits) this would reduce things from 4G to 2G.

On Pluto, the largest is 1280 bytes, M2k is 492, so, even 32k seems
pretty large.

Signed-off-by: Robin Getz <[email protected]>
  • Loading branch information
rgetz committed Apr 22, 2020
1 parent 4841791 commit eed04bd
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
25 changes: 21 additions & 4 deletions channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,16 @@ static char * get_scan_element(const struct iio_channel *chn, size_t *length)
/* Returns a string containing the XML representation of this channel */
char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
{
size_t len = sizeof("<channel id=\"\" name=\"\" "
"type=\"output\" ></channel>")
+ strlen(chn->id) + (chn->name ? strlen(chn->name) : 0);
char *ptr, *str, **attrs, *scan_element = NULL;
ssize_t len;
char *ptr, *eptr, *str, **attrs, *scan_element = NULL;
size_t *attrs_len, scan_element_len = 0;
unsigned int i;

len = sizeof("<channel id=\"\" type=\"\" ></channel>");
len += strnlen(chn->id, MAX_CHN_ID);
len += chn->is_output ? sizeof("output") : sizeof("input");
len += chn->name ? sizeof(" name= ") + strnlen(chn->name, MAX_CHN_NAME) : 0;

if (chn->is_scan_element) {
scan_element = get_scan_element(chn, &scan_element_len);
if (!scan_element)
Expand Down Expand Up @@ -260,26 +263,32 @@ char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
str = malloc(len);
if (!str)
goto err_free_attrs;
eptr = str + len;

iio_snprintf(str, len, "<channel id=\"%s\"", chn->id);
ptr = strrchr(str, '\0');
len = eptr - ptr;

if (chn->name) {
sprintf(ptr, " name=\"%s\"", chn->name);
ptr = strrchr(ptr, '\0');
len = eptr - ptr;
}

sprintf(ptr, " type=\"%s\" >", chn->is_output ? "output" : "input");
ptr = strrchr(ptr, '\0');
len = eptr - ptr;

if (chn->is_scan_element) {
strcpy(ptr, scan_element);
ptr += scan_element_len;
len -= scan_element_len;
}

for (i = 0; i < chn->nb_attrs; i++) {
strcpy(ptr, attrs[i]);
ptr += attrs_len[i];
len -= attrs_len[i];
free(attrs[i]);
}

Expand All @@ -289,6 +298,14 @@ char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)

strcpy(ptr, "</channel>");
*length = ptr - str + sizeof("</channel>") - 1;
len -= sizeof("</channel>");

if (len < 0) {
IIO_ERROR("Internal libIIO error: iio_channel_get_xml str length isssue\n");
free(str);
return NULL;
}

return str;

err_free_attrs:
Expand Down
3 changes: 3 additions & 0 deletions iio-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
#define CLEAR_BIT(addr, bit) \
*(((uint32_t *) addr) + BIT_WORD(bit)) &= ~BIT_MASK(bit)

/* 256 is the MAX_NAME (file name) on Linux, 4096 is PAGESIZE */
#define MAX_CHN_ID 256 /* encoded in the sysfs filename */
#define MAX_CHN_NAME 256 /* encoded in the sysfs filename */

/* ntohl/htonl are a nightmare to use in cross-platform applications,
* since they are defined in different headers on different platforms.
Expand Down

0 comments on commit eed04bd

Please sign in to comment.