That's right, when a bounds checked array is converted to a pointer, the bounds does not go with it. Presumably, the function receiving the p has some way to determine the length (such as strlen, or via another parameter) from which the correct array can be reconstructed by doing a slice.
> What if the line was: int a[..] = p[0..12] Do we still get undefined behaviour?
Yes, if the 12 extends past the end of the data p points to.
> Assuming that a indexes from 0 to 9, what happens when we use p with an out of range index, for example: int *p = &a[8]; blah = p[3];
You get undefined behavior.
> My main concern is how to tell other functions that the array has a maximum size
The same way it's done now, by strlen, passing another argument with the length, or the function is able to get the length by other means. When a bounds checked array is converted to a pointer, the bounds are not part of the pointer.