You can get away with malloc and free with the risks of poking holes in the heap depending what the rest of the code does (how other dynamic memory allocation work).
but why would you keep a poor design...
if you want to play with dynamic memory, then build in a local buffer and return a String instance built from that buffer