Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Right. Also it might it sound like array-to-pointer decay is forced onto the programmer. Instead, you can take the address of an array just fine without letting it decay. The type then preserves the length.


C: int foo(int a[]) { return a[5]; }

    int main() {
        int a[3];
        return foo(a);
    }

    > gcc test.c
    > ./a.out
Oops.

D: int foo(int[] a) { return a[5]; }

    int main() {
        int[3] a;
        return foo(a);
    }

    > ./cc array.d
    > ./array
    [email protected](1): index [5] is out of bounds for array of length 3
Ah, Nirvana!

How to fix it for C:

https://www.digitalmars.com/articles/C-biggest-mistake.html


You need to take the address of the array instead of letting it decay and then size is encoded in the type:

  int foo(int (*a)[6]) { return a[5]; }
  int main() {
  int a[3];
    return foo(&a);
  }
Or for run-time length:

  int foo(int n, int (*a)[n]) { return (\*a)[5]; }
  int main() {
    int a[3];
    return foo(ARRAY_SIZE(a), &a);
  }
  /app/example.c:4:38: runtime error: index 5 out of bounds for 
 type 'int[n]'
https://godbolt.org/z/dxx7TsKbK\*


  int foo(int n, int (*a)[n]) { return (\*a)[5]; }
  int main() {
    int a[3];
    return foo(ARRAY_SIZE(a), &a);
  }
That syntax is why array overflows remain the #1 problem with C bugs in shipped code. It isn't any better than:

  int foo(size_t n, int* a) { assert(5 < n); return a[5]; }
  int main() {
    int a[3];
    return foo(ARRAY_SIZE(a), a);
  }
as the array dimension has to be handled separately from the pointer.

Contrast with how simple it is in D:

    int foo(int[] a) { return a[5]; }
    int main() {
        int[3] a;
        return foo(a);
    }
and the proof is shown by array overflow bugs in the wild are stopped cold. It can be that simple and effective in C.


\* what operator is this? I have never seen it. Where can I read about it?


My guess is that it was intended to escape the * since unescaped * in regular text on HN results in italics. Since the text in question is in a code block, though, that escaping is not needed.


This should be caught by CHERI.


Nice, when you know the length at compile time, which is rarely from my experience.

The holy grail is runtime access to the length, which means an array would have to be backed by something more elaborate.


Oh, it also work for runtime length:

https://godbolt.org/z/PnaWWcK9o


Now try that on a compiler without -fsanitize=bounds, yet full ISO C compliant.


You can still access the size which is what the parent was asking for. And please tell me how you would try this on an ISO compliant compiler for D.


D has bounds checking, and isn't a ISO language.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: