0

I have this snippet of code:

new->name = zalloc(sizeof(char) * strlen(name) + 1);
if (!new->name)
    goto alloc_failed;
strcpy(new->name, name);

Is the general use if strcpy() frowned upon even if space for name was pre-allocated. Just wondering for secure purposes. Is is better to use strncpy() or srtlcpy().

Andrew Ricci
  • 475
  • 5
  • 21
  • The choice between `strcpy` and `strlcpy` is a matter of opinion and the only opinion that matters is that of person funding your paycheck, or grading your assignments. OTOH, I think most would agree that `strncpy` is a bad choice, since it doesn't guarantee that the output will be NUL terminated (hence you'll need extra code to NUL terminate the string). – user3386109 Apr 20 '15 at 02:32
  • memcpy makes more sense here since you know the length – David Heffernan Apr 20 '15 at 04:23

2 Answers2

1

Your coding example has some small issues:

new->name = zalloc(sizeof(char) * strlen(name) + 1);
if (!new->name)
    goto alloc_failed;
strcpy(new->name, name);

The size allocated is computed as sizeof(char) * strlen(name) + 1. If you insist on multiplying by sizeof(char) which by definition equals 1, you should at least write: sizeof(char) * (strlen(name) + 1). Barring that, your use of strcpy is fine in this example, but it would be more efficient to store the size in a local variable and use memcpy:

{
    size_t size = strlen(name) + 1;
    new->name = zalloc(size);
    if (!new->name)
        goto alloc_failed;
    memcpy(new->name, name, size);
}

Also note that POSIX systems have strdup() that does just the same thing using malloc. If zalloc() is a thin wrapper on malloc() that allocates and initializes the memory to zero from a single size argument, you can use strdup() as a simple replacement for this code. If it is a custom memory allocation scheme, you should also provide zstrdup() as duplicating character strings is common place in many C programs.

Another small remark on style: using goto is fine here if the local coding conventions condone it, but it would be preferable not to use obvious C++ keywords such as new and delete as plain identifiers.

Regarding strlcpy(), it may or may not be available on your platform but is a good option for other places. strncpy() OTOH is best avoided. It is a standard C function, but its semantics are so inconsistent with the rest of the C library that it is very often misused:

  • The famous shortcoming is strncpy() does not tack a '\0' at the end of the destination if the source string is longer than the size parameter. snprintf(dest, size, "%s", src); would do that but is probably not very efficient.

  • A less known side effect of strncpy occurs when the source string is shorter than the size parameter: the destination array is padded with '\0' all the way to the end. Using strncpy() to avoid buffer overflows is very inefficient if the destination array is substantially longer than the source.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
-1

You should use strcpy when you know what the max limit of the data possible is, and strncpy when it is user defined.

Your use of strcpy in this example is ok.

Deanie
  • 2,316
  • 2
  • 19
  • 35
  • [strcpy and relatives should not be used anymore](http://blog.smartbear.com/codereviewer/c11-a-new-c-standard-aiming-at-safer-programming/). In that term, the question is justified. strcpy at least should not be used anymore. – too honest for this site Apr 20 '15 at 02:14
  • 3
    It's a general misconception that strncpy is safer than strcpy. It is not. It just trades one problem (buffer overflow) for another (non-null terminated strings). The big problem with strncpy is that using it may produce non-null terminated char buffers. This can result in dangerous bugs and exploits. Google "strncpy unsafe". For example: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/ – kaylum Apr 20 '15 at 02:31
  • There is no trade-off. Buffer overflow cannot be handled in strcpy, while the potentially missing NUL-termination can easily be added afterwards by setting the last entry of the buffer explicitly. So, you do really want to tell, both have the same issues? – too honest for this site Apr 20 '15 at 02:48
  • @Olaf That may *seem* reasonable, but in general bound checks should only be made on interface boundaries, cause constantly checking all the not-so-obvious invariants is excessive by definition. – user3125367 Apr 20 '15 at 02:53
  • 1
    Better safe than sorry (yes, I know the original version). For most modern systems, this is no issue at all and some extra checking has none to negligble performance impact for far by most code. Safe code is much more important for this. Highly optimized code is already encapsulated in few modules and there optimizations are certainly justified. However, this should be applied intentionally; the default should be to play safe first, Especially to get this into the mindes of novice programmers! There is enough unsafe software in the world. – too honest for this site Apr 20 '15 at 03:01
  • @AlanAu: Btw: don't forget we are talking about C; that article is about C++ in most parts. For desktop, I actually perfer high-level languages with strong typing like Python, which do not have _these_(!) problems. – too honest for this site Apr 20 '15 at 03:06
  • @Olaf Agreed. OTOH (and imho) if we do all that safeside ifs/asserts *in C*, we just get ugly-wordy version of jvm or clr written by hand. C[++] is a presentation of bare metal that isn't safe and requires our constant efforts to keep all implementation details together without adding line-noise overhead (not even mentioning runtime), otherwise you just picked a wrong tool. Unsafety is vm-choice-makers failure, not developer's. – user3125367 Apr 20 '15 at 03:22
  • @user3125367: I found the phrase now: learn to stand and walk before you learn to run;-). I do absolutely agree, especially as I write embedded software in C, where I have to trade-off permanently (interrupt handler, etc.) between speed and checking overhead. That might be also the reason why I am very picky about possible security holes. – too honest for this site Apr 20 '15 at 03:34