с заданием
buffer = tmp
у вас есть два указателя, указывающих на одну и ту же память. Это можно посмотреть примерно так:
+-----+
| tmp | --\
+-----+ \ +--------------------------------+
>--> | memory allocated by realloc... |
+--------+ / +--------------------------------+
| buffer | --/
+--------+
Поскольку у вас есть только одно выделение, вызов
free(tmp);
освободит это единственное распределение. После этого звонка на free
у вас есть что-то вроде
+-----+
| tmp | --\
+-----+ \ +-----------------------+
>--> | unallocated memory... |
+--------+ / +-----------------------+
| buffer | --/
+--------+
Это означает, что любое разыменование buffer
будет недопустимым, поскольку также указывает на эту нераспределенную память. И, конечно, любой дальнейший вызов realloc
также недопустим, поскольку перераспределять нечего.
Решение простое: не вызывайте free
в цикле.