To be very clear: after saying
int *p1 = malloc(5);
if you then say
p1[0] = 1;
you are probably okay, if on your machine type int
is 32 bits (4 bytes) or less. But if you say
p1[1] = 2;
you are probably not okay: you have probably written to bytes 4-7 of the malloc'ed region, i.e. more than you asked for, and you have committed undefined behavior. Anything might happen: you might store that value 2
without causing any other problems, you might overwrite some other variable or data structure (leading to subtle and difficult-to-diagnose bugs), you might get an immediate segmentation violation or other memory access error, you might corrupt memory in such a way that you get a segmentation violation or other memory access error some time later (which is a very difficult-to-diagnose bug). What you will almost certainly not get is a nice, clear error saying "array overflow".
It's a little easier to explain with a slightly more appropriate allocation. If you say
int *p2 = malloc(5 * sizeof(int));
then p2[0] = 1
is fine, and p2[4] = 5
is fine, but p2[5] = 6
is undefined behavior. Or if you say
char *p3 = malloc(5);
then p3[0] = '1'
is fine, and p3[4] = '5'
is fine, but p3[5] = '6'
is undefined behavior.