Skip to content

Commit

Permalink
Merge pull request #444 from analogdevicesinc/rgetz-remove-strcpy2
Browse files Browse the repository at this point in the history
remove strcpy
  • Loading branch information
dNechita authored Apr 23, 2020
2 parents 65cc33b + 1fa3040 commit c68c16f
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 64 deletions.
58 changes: 41 additions & 17 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,35 +263,56 @@ char * iio_channel_get_xml(const struct iio_channel *chn, size_t *length)
str = malloc(len);
if (!str)
goto err_free_attrs;
ptr = str;
eptr = str + len;

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

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

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

if (chn->is_scan_element) {
strcpy(ptr, scan_element);
if (chn->is_scan_element && len > scan_element_len) {
memcpy(ptr, scan_element, scan_element_len); /* Flawfinder: ignore */
ptr += scan_element_len;
len -= scan_element_len;
}

for (i = 0; i < chn->nb_attrs; i++) {
strcpy(ptr, attrs[i]);
ptr += attrs_len[i];
if (len > attrs_len[i]) {
memcpy(ptr, attrs[i], attrs_len[i]); /* Flawfinder: ignore */
ptr += attrs_len[i];
len -= attrs_len[i];
}
free(attrs[i]);
}

free(scan_element);
free(attrs);
free(attrs_len);

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

*length = ptr - str;

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
77 changes: 50 additions & 27 deletions context.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,25 @@ static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
/* Returns a string containing the XML representation of this context */
char * iio_context_create_xml(const struct iio_context *ctx)
{
size_t len, *devices_len = NULL;
char *str, *ptr, **devices = NULL;
ssize_t len;
size_t *devices_len = NULL;
char *str, *ptr, *eptr, **devices = NULL;
unsigned int i;

len = strlen(ctx->name) + sizeof(xml_header) - 1 +
sizeof("<context name=\"\" ></context>");
if (ctx->description)
len += strlen(ctx->description) +
sizeof(" description=\"\"") - 1;
len = sizeof(xml_header) - 1;
len += strnlen(ctx->name, MAX_CTX_NAME);
len += sizeof("<context name=\"\" ></context>") - 1;

for (i = 0; i < ctx->nb_attrs; i++)
len += strlen(ctx->attrs[i]) +
strlen(ctx->values[i]) +
sizeof("<context-attribute name=\"\" value=\"\" />");
if (ctx->description) {
len += strnlen(ctx->description, MAX_CTX_DESC);
len += sizeof(" description=\"\"") - 1;
}

for (i = 0; i < ctx->nb_attrs; i++) {
len += strnlen(ctx->attrs[i], MAX_ATTR_NAME);
len += strnlen(ctx->values[i], MAX_ATTR_VALUE);
len += sizeof("<context-attribute name=\"\" value=\"\" />") - 1;
}

if (ctx->nb_devices) {
devices_len = malloc(ctx->nb_devices * sizeof(*devices_len));
Expand Down Expand Up @@ -94,32 +99,50 @@ char * iio_context_create_xml(const struct iio_context *ctx)
errno = ENOMEM;
goto err_free_devices;
}

if (ctx->description) {
iio_snprintf(str, len, "%s<context name=\"%s\" "
"description=\"%s\" >",
xml_header, ctx->name, ctx->description);
} else {
iio_snprintf(str, len, "%s<context name=\"%s\" >",
xml_header, ctx->name);
eptr = str + len;
ptr = str;

if (len > 0) {
if (ctx->description) {
ptr += iio_snprintf(str, len, "%s<context name=\"%s\" "
"description=\"%s\" >",
xml_header, ctx->name, ctx->description);
} else {
ptr += iio_snprintf(str, len, "%s<context name=\"%s\" >",
xml_header, ctx->name);
}
len = eptr - ptr;
}

ptr = strrchr(str, '\0');

for (i = 0; i < ctx->nb_attrs; i++)
ptr += sprintf(ptr, "<context-attribute name=\"%s\" value=\"%s\" />",
for (i = 0; i < ctx->nb_attrs && len > 0; i++) {
ptr += iio_snprintf(ptr, len, "<context-attribute name=\"%s\" value=\"%s\" />",
ctx->attrs[i], ctx->values[i]);

len = eptr - ptr;
}

for (i = 0; i < ctx->nb_devices; i++) {
strcpy(ptr, devices[i]);
ptr += devices_len[i];
if (len > devices_len[i]) {
memcpy(ptr, devices[i], devices_len[i]); /* Flawfinder: ignore */
ptr += devices_len[i];
len -= devices_len[i];
}
free(devices[i]);
}

free(devices);
free(devices_len);
strcpy(ptr, "</context>");

if (len > 0) {
ptr += iio_strlcpy(ptr, "</context>", len);
len -= sizeof("</context>") - 1;
}

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

return str;

err_free_devices:
Expand Down
75 changes: 55 additions & 20 deletions device.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,18 @@ static char *get_attr_xml(const char *attr, size_t *length, enum iio_attr_type t
/* Returns a string containing the XML representation of this device */
char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
{
size_t len = sizeof("<device id=\"\" name=\"\" ></device>")
+ strlen(dev->id) + (dev->name ? strlen(dev->name) : 0);
char *ptr, *str, **attrs, **channels, **buffer_attrs, **debug_attrs;
ssize_t len;
char *ptr, *eptr, *str, **attrs, **channels, **buffer_attrs, **debug_attrs;
size_t *attrs_len, *channels_len, *buffer_attrs_len, *debug_attrs_len;
unsigned int i, j, k;

len = sizeof("<device id=\"\" ></device> ") - 1;
len += strnlen(dev->id, MAX_DEV_ID);
if (dev->name) {
len += sizeof(" name=\"\"") - 1;
len += strnlen(dev->name, MAX_DEV_NAME);
}

attrs_len = malloc(dev->nb_attrs * sizeof(*attrs_len));
if (!attrs_len)
return NULL;
Expand Down Expand Up @@ -143,56 +149,85 @@ char * iio_device_get_xml(const struct iio_device *dev, size_t *length)
str = malloc(len);
if (!str)
goto err_free_debug_attrs;
eptr = str + len;
ptr = str;

iio_snprintf(str, len, "<device id=\"%s\"", dev->id);
ptr = strrchr(str, '\0');
if (len > 0) {
ptr += iio_snprintf(str, len, "<device id=\"%s\"", dev->id);
len = eptr - ptr;
}

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

strcpy(ptr, " >");
ptr += 2;
if (len > 0) {
ptr += iio_strlcpy(ptr, " >", len);
len -= 2;
}

for (i = 0; i < dev->nb_channels; i++) {
strcpy(ptr, channels[i]);
ptr += channels_len[i];
if (len > channels_len[i]) {
memcpy(ptr, channels[i], channels_len[i]); /* Flawfinder: ignore */
ptr += channels_len[i];
len -= channels_len[i];
}
free(channels[i]);
}

free(channels);
free(channels_len);

for (i = 0; i < dev->nb_attrs; i++) {
strcpy(ptr, attrs[i]);
ptr += attrs_len[i];
if (len > attrs_len[i]) {
memcpy(ptr, attrs[i], attrs_len[i]); /* Flawfinder: ignore */
ptr += attrs_len[i];
len -= attrs_len[i];
}
free(attrs[i]);
}

free(attrs);
free(attrs_len);

for (i = 0; i < dev->nb_buffer_attrs; i++) {
strcpy(ptr, buffer_attrs[i]);
ptr += buffer_attrs_len[i];
if (len > buffer_attrs_len[i]) {
memcpy(ptr, buffer_attrs[i], buffer_attrs_len[i]); /* Flawfinder: ignore */
ptr += buffer_attrs_len[i];
len -= buffer_attrs_len[i];
}
free(buffer_attrs[i]);
}

free(buffer_attrs);
free(buffer_attrs_len);

for (i = 0; i < dev->nb_debug_attrs; i++) {
strcpy(ptr, debug_attrs[i]);
ptr += debug_attrs_len[i];
if (len > debug_attrs_len[i]) {
memcpy(ptr, debug_attrs[i], debug_attrs_len[i]); /* Flawfinder: ignore */
ptr += debug_attrs_len[i];
len -= debug_attrs_len[i];
}
free(debug_attrs[i]);
}

free(debug_attrs);
free(debug_attrs_len);

strcpy(ptr, "</device>");
*length = ptr - str + sizeof("</device>") - 1;
if (len > 0) {
ptr += iio_strlcpy(ptr, "</device>", len);
len -= sizeof("</device>") - 1;
}

*length = ptr - str;

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

return str;

err_free_debug_attrs:
Expand Down
10 changes: 10 additions & 0 deletions iio-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@
#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 */
#define MAX_DEV_ID 256 /* encoded in the sysfs filename */
#define MAX_DEV_NAME 256 /* encoded in the sysfs filename */
#define MAX_CTX_NAME 256 /* nominally "xml" */
#define MAX_CTX_DESC 256 /* nominally "linux ..." */
#define MAX_ATTR_NAME 256 /* encoded in the sysfs filename */
#define MAX_ATTR_VALUE 4096 /* Linux page size, could be anything */

/* ntohl/htonl are a nightmare to use in cross-platform applications,
* since they are defined in different headers on different platforms.
Expand Down Expand Up @@ -289,6 +298,7 @@ void iio_channel_init_finalize(struct iio_channel *chn);
unsigned int find_channel_modifier(const char *s, size_t *len_p);

char *iio_strdup(const char *str);
size_t iio_strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize);

int iio_context_add_attr(struct iio_context *ctx,
const char *key, const char *value);
Expand Down
43 changes: 43 additions & 0 deletions utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,46 @@ char *iio_strdup(const char *str)
return buf;
#endif
}

/* strlcpy is designed to be safer, more consistent, and less error prone
* replacements for strncpy, since it guarantees to NUL-terminate the result.
*
* This function
* Copyright (c) 1998, 2015 Todd C. Miller <[email protected]>
* https://github.com/freebsd/freebsd/blob/master/sys/libkern/strlcpy.c
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* Copy string src to buffer dst of size dsize. At most dsize-1
* chars will be copied. Always NUL terminates (unless dsize == 0).
* Returns strlen(src); if retval >= dsize, truncation occurred.
*
* src is assumed to be null terminated, if it is not, this function will
* dereference unknown memory beyond src.
*/
size_t iio_strlcpy(char * __restrict dst, const char * __restrict src, size_t dsize)
{
const char *osrc = src;
size_t nleft = dsize;

/* Copy as many bytes as will fit. */
if (nleft != 0) {
while (--nleft != 0) {
if ((*dst++ = *src++) == '\0')
break;
}
}

/* Not enough room in dst, add NUL and traverse rest of src. */
if (nleft == 0) {
if (dsize != 0)
*dst = '\0'; /* NUL-terminate dst */

while (*src++)
;
}

return(src - osrc - 1); /* count does not include NUL */
}

0 comments on commit c68c16f

Please sign in to comment.