2
\$\begingroup\$

I'd like to know if i respect strlcat(3) behiour with my implementation, cause i'm not really sure to understand strlcat particular behaviour

int my_strlcat(char *dest, char *src, int size)
{
  int i;
  int src_len;
  int dest_len;

  i = 0;
  dest_len = strlen(dest);
  src_len = strlen(src);
  if (size <= 0)
   return dest_len;
  while (dest_len < size)
  {
    dest[dest_len] = src[i];
    dest_len++;
    i++;
  }
  dest[dest_len] = '\0';
  return (strlen(dest));
}
\$\endgroup\$
2
  • 2
    \$\begingroup\$ In general, using signed types for sizes and anything but size_t for things of arbitrary size is a bad idea. \$\endgroup\$
    – Alex
    Oct 12, 2011 at 13:01
  • \$\begingroup\$ If dest does not already contain a nil-terminated string, or contains one that overflows dest (e.g. because someone previously used strcat()), then strlen() could return a value larger than size and you're already boned. You should replace the strlen() call with some code of your own that stops counting when it reaches size. \$\endgroup\$ Jan 11, 2017 at 20:29

4 Answers 4

0
\$\begingroup\$
while (dest_len < size)
  {
    dest[dest_len] = src[i];
    dest_len++;
    i++;
  }
dest[dest_len] = '\0';

At the end of the loop dest_len will be equal to size, and the dest[des_len] will write beyond the allowed offset.

UPDATE: this will probably work

size_t my_strlcat(char *dest, char *src, size_t size)
{
size_t src_len, dest_len;

  dest_len = strlen(dest);
  src_len = strlen(src);

  if (dest_len+src_len>= size) return dest_len+src_len;

  memcpy(dest+dest_len, src, src_len+1);

  return dest_len+src_len;
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ This is inefficient, you end up iterating over src twice, making this not O(N + M) but O(N + M*2). \$\endgroup\$
    – Pharap
    Sep 3, 2018 at 17:54
2
\$\begingroup\$
  • src_len is not used..
  • the strlen in the return statement is not needed.. you know the length from dest_len.

IMHO very weird implementation :)

\$\endgroup\$
2
\$\begingroup\$

There are a few things wrong if this is meant to be a implementation of the standard strlcat():

  • The function definition should be of the form: size_t my_strlcat(char *dst, const char *src, size_t size);
  • You are always overflowing the destination buffer by one when you NUL terminate.
  • You are overflowing the source buffer reads depending on the input. For example, consider if dest_len=1, src_len=2 and size=1000.
  • While not wrong it is better to try to minimize the use of strlen() unless needed. You probably only need one strlen(dest).

See here for an example implementation of strlcat().

\$\endgroup\$
0
\$\begingroup\$

You're basically right I think. Checking the man page for strlcpy() shows one discrepancy I can see - the null termination of the destination only happens if there's room in dest after the copying. Although that seems kind of dangerous to me, it depends how well you want to replicate the semantics. Your current implementation always null-terminates, which is nice and safe but might end up diverging from the stock implementation in that edge case.

For performance, you should check size <= 0 before you strlen() both of the strings, as in that case you only need to call strlen(dest). That might seem minor, but strlen runs in O(N) time so you don't want to be calling it if you don't have to. So basically just move the check on size to before the call to strlen(src).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.