Get rid of the auto char array and make them pass the size so you can check for overflow.
#define I32TOA( buff, val ) _i32toa( (buff), sizeof(buff), (val) )
char * _i32toa(char *const rtn, size_t size, int32_t i) {
if (NULL == rtn) return NULL;
uint32_t ut, ui;
char minus_sign=0;
char *p = rtn + size-1;
*p-- = 0; // nul-terminate buffer
assert( p >= rtn );
if (i < 0) {
minus_sign = '-';
ui = (uint32_t)((int)-1 * (int)i);
} else {
ui = i;
}
while (ui > 9) {
ut = ui;
ui /= 10;
*p-- = (ut - (ui * 10)) + 48;
assert( p >= rtn );
}
*p = ui + 48;
if ('-' == minus_sign) {
*--p = minus_sign;
assert( p >= rtn );
}
return p;
}