shadow-maint / shadow

Upstream shadow tree
Other
304 stars 232 forks source link

How large is the universe? #1052

Closed alejandro-colomar closed 3 months ago

alejandro-colomar commented 3 months ago

https://github.com/shadow-maint/shadow/blob/63297e836d000db7928b02cf9608796346705611/lib/chkname.c#L36-L48

Cc: @stoeckmann

The maximum number of elements in an array object in C is PTRDIFF_MAX.

Long story:

The ISO C standard says that an implementation must support objects of at least 2^16 - 1 bytes. This is of course not the actual limit.

The standard specifies that it is valid to subtract two pointers that point to different elements of the same array object, and that the result is of ptrdiff_t type. This implies that the number of elements in an array object must be representable in a ptrdiff_t, and so the maximum number of elements in an array object is implicitly defined as not larger than PTRDIFF_MAX.

Since both the compiler and libc usually have to access objects as raw bytes, they'll also have to subtract pointers to bytes, and so the limit is further restricted to just PTRDIFF_MAX bytes (not just elements).

Here's some proof that the compiler doesn't allow objects larger than PTRDIFF_MAX bytes:

$ cat huge.c 
#include <stdint.h>

int
main(void)
{
    char  a[PTRDIFF_MAX - 1];
    char  b[PTRDIFF_MAX];
    char  c[PTRDIFF_MAX + 1ul];

    int   d[PTRDIFF_MAX - 1];
    int   e[PTRDIFF_MAX];
    int   f[PTRDIFF_MAX + 1ul];

    int   g[PTRDIFF_MAX/4 - 1];
    int   h[PTRDIFF_MAX/4];
    int   i[PTRDIFF_MAX/4 + 1];
}
$ cc -Wall -Wextra huge.c -Wno-unused-variable
huge.c: In function ‘main’:
huge.c:8:15: error: size of array ‘c’ is too large
    8 |         char  c[PTRDIFF_MAX + 1ul];
      |               ^
huge.c:10:15: error: size of array ‘d’ exceeds maximum object size ‘9223372036854775807’
   10 |         int   d[PTRDIFF_MAX - 1];
      |               ^
huge.c:11:15: error: size of array ‘e’ exceeds maximum object size ‘9223372036854775807’
   11 |         int   e[PTRDIFF_MAX];
      |               ^
huge.c:12:15: error: size of array ‘f’ is too large
   12 |         int   f[PTRDIFF_MAX + 1ul];
      |               ^
huge.c:16:15: error: size ‘9223372036854775808’ of array ‘i’ exceeds maximum object size ‘9223372036854775807’
   16 |         int   i[PTRDIFF_MAX/4 + 1];
      |               ^

https://discourse.llvm.org/t/problems-with-objects-larger-than-ptrdiff-max/41126/6


Thus, whether implementations want to recognize it or not, objects have size limits. If an implementation claims that there's no limit, it's probably lying or unaware of its own limitations.

Let's hard code a strong limit of MIN(whatever, PTRDIFF_MAX).