Why is rsize_t defined?

zangw picture zangw · Nov 9, 2015 · Viewed 11.1k times · Source

I found that strncpy_s() is defined under VS2013 as

errno_t __cdecl strncpy_s
(
  _Out_writes_z_(_SizeInBytes) char * _Dst, 
  _In_ rsize_t _SizeInBytes, 
  _In_reads_or_z_(_MaxCount) const char * _Src, 
  _In_ rsize_t _MaxCount
);

rsize_t is:

typedef size_t rsize_t;

I think it's a trick done by Visual Studio. However, I found this function defined as follows on this page

errno_t strncpy_s
(
  char *restrict dest,
  rsize_t destsz,
  const char *restrict src, 
  rsize_t count
); 

Why is rsize_t defined here?

What if size_t was used here?

Any special cases to use this rsize_t?

Answer

You've encountered it in Microsoft's C++ standard library, but it actually comes from C. C 11, to be precise, which means it's not technically a part of C++.

C 11 standard, Annex K introduced all the _s functions and the corresponding typedefs, including rsize_t. There is also a "maximum value" macro RSIZE_MAX which is large enough for typical applications, but smaller than the real maximum value of the type. The secure functions do nothing and report an error when a value of type rsize_t exceeds RSIZE_MAX.

The idea is to avoid crashes on buffer overruns and similar errors caused by invalid sizes, usually resulting from using a negative value for size. In 2's complement signed value representation (the most common one), a negative number corresponds to a very large number when treated as unsigned. RSIZE_MAX should catch such incorrect use.

Quoting the "rationale" part of C11 (N1570), K.3.2:

3 Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like size_t. Also, some implementations do not support objects as large as the maximum value that can be represented by type size_t.

4 For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect programming errors. For implementations targeting machines with large address spaces, it is recommended that RSIZE_MAX be defined as the smaller of the size of the largest object supported or (SIZE_MAX >> 1), even if this limit is smaller than the size of some legitimate, but very large, objects. Implementations targeting machines with small address spaces may wish to define RSIZE_MAX as SIZE_MAX, which means that there is no object size that is considered a runtime-constraint violation.


It is worth noting that Annex K has very few implementations and there is a proposal (N1967) to deprecate and/or remove it from the standard.