From: "The Fungi" <fungi@yuggoth.org> > On Fri, Jan 10, 2003 at 12:10:37PM -0600, Ronald Fenner wrote: > > sprintf(temp, "\r\n &c%s list&n\r\n", guild_types[i]); > > strcat(buf, temp); > > The method I've been using is: > > len += snprintf(buf + len, sizeof(buf) - len, > "\r\n &c%s list&n\r\n", guild_types[i]); > > Which will ensure that you never overflow buf so long as you always > keep len == sizeof(buf), might not even be a bad idea to assert() > that if there are general-use functions doing this that you're > afraid your developers might misuse. Actually the snprintf statement itself will never overflow, period. len will only be added to if space is left in the string for writing. Putting in an assert() would be pointless, unless you're doing some manual additions beside the snprintf(). > A friend of mine even suggested > making a struct, maybe called checked_string, that associates an int > for "len" with a fixed-size string. Making further structs is only necessary if you wish the buffer to be inherited into the functions below it, and only then if you don't wish to add a size_t argument to the function. To illustrate: void foo(char *buf, size_t max_len) { size_t len; int i = 10; len = snprintf(buf, max_len, "foo list:\r\n"); while (i--) len += snprintf(buf + len, max_len - len, " foo %d\r\n", i); } void bar(void) { char buffer[100]; foo(&buffer, sizeof(buffer)); } The function foo() will never overflow the buffer, since it is passed the maximum length available. Adding a checked string struct as you suggested would alter the appearance, but the functionality is about the same[1]: typedef struct { char *buffer; size_t max_len; } string; /* or checked_string, or whatever */ string *new_string(size_t max_len) { string *new; CREATE(new, string, 1); CREATE(new->buffer, char, max_len); new->max_len = max_len; return new; } void free_string(string *str) { if (str->buffer) free(str->buffer); free(str); } void foo(string *str) { size_t len; int i = 10; len = snprintf(str->buffer, str->max_len, "foo list:\r\n"); while (i--) len += snprintf(str->buffer + len, str->max_len - len, " foo %d\r\n", i); } void bar(void) { string *str = new_string(100); foo(str); free_string(str); } The only advantage to this approach, as far as I can see, is not having to make sure you pass the size parameter along with the char pointer. The downside is having to free_string() all of the allocated strings. Welcor [1] I added the general string handling routines. Everything here is mailer code and may not work if compiled. -- +---------------------------------------------------------------+ | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html | | Newbie List: http://groups.yahoo.com/group/circle-newbies/ | +---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 06/26/03 PDT