3

From this video on youtube by Kees Cook from linux.conf.au 2019 he mentions strscpy as being preferred but generally doing what users want (less NUL-padding). However, he doesn't say what defines this (spec or header),

Slide from the video,

strscpy slide

I can't find strscpy() with man

$ for i in strcpy strlcpy strscpy; do man -w $i; done;
/usr/share/man/man3/strcpy.3.gz
/usr/share/man/man3/strlcpy.3bsd.gz
No manual entry for strscpy
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • 3
    https://mafford.com/text/the-many-ways-to-copy-a-string-in-c/ – Iłya Bursov Feb 08 '19 at 22:45
  • 1
    `strscpy()` it not part of C, nor of POSIX. It is an extension. Using it make the code unportable. – alk Feb 09 '19 at 09:08
  • strscpy does its thing safely, but I don't think silent truncation is what users generally want. It is nit standard anyway. The standard (but optional and not supported by glibc) function that does the same thing is strcpy_s. – n. m. could be an AI Aug 25 '19 at 13:40

2 Answers2

5

It's in the linux source, not in the standard library. Online man page

AShelly
  • 34,686
  • 15
  • 91
  • 152
  • 1
    Shoulf we expect it to be added into GLibc? – Some Name Feb 09 '19 at 05:37
  • 3
    @SomeName: Not all functions, provided in the Linux kernel, are really needed for user-space programs. And, in my opinion, `strscpy` is one of them: it very cares about non-trusted strings, which may come from the user space (and shouldn't make the kernel to crash in any case), but this feature is not so crucial for user-space programs. See also [this reasoning](https://mafford.com/text/the-many-ways-to-copy-a-string-in-c/) about some functions added to the Linux kernel. – Tsyvarev Feb 09 '19 at 18:56
1

Given that there isn't any library that provides this function (AFAIK), you can write it yourself. I'm sure it can be optimized, but a very simple definition using GNU C11 for it is this one, which I use:

#pragma once    /* libalx/base/string/strcpy/strscpy.h */


#include <stddef.h>


__attribute__((nonnull))
ptrdiff_t strscpy       (char dest[restrict /*size*/],
                         const char src[restrict /*size*/],
                         ptrdiff_t size);
#include "libalx/base/string/strcpy/strscpy.h"

#include <errno.h>
#include <stddef.h>
#include <string.h>


ptrdiff_t strscpy       (char dest[restrict /*size*/],
                         const char src[restrict /*size*/],
                         ptrdiff_t size)
{
        ptrdiff_t   len;

        if (size <= 0)
                return  -E2BIG;

        len     = strnlen(src, size - 1);
        memcpy(dest, src, len);
        dest[len] = '\0';

        return  len;
}

Note: I prefer ptrdiff_t for array sizes, but you can use size_t/ssize_t as the linux version does.