The problem of the current restore process is that every record is inserted in its own looper roundtrip and thus using its own savepoint. The savepoint number is 32-bit and it wraps around after 2^32 iterations. This particular issue is not related to GBAK, it's common to any single transaction modifying billions of records. Fortunately, old dumb savepoint handling is tolerate to such a wraparound in trivial cases, so GBAK is not affected.
Second part of the problem appears when this transaction has also a deferred work (uncommitted DDL). AFAIU, the legacy code implicitly assumes that there cannot be savepoint number zero, but it becomes possible due to wraparound. So DFW_merge_work() is called with old_sav_number = 0 and new_sav_number = 0 and it enters an infinite loop, causing a hang.
Workaround for GBAK's restore is to use the -o switch, which restores every table in its own transaction (and also separates a DDL transaction from multiple DML transactions).
A noticable improvement could be to avoid savepoints during restore at all. IIRC, InterBase has added the isc_tpb_no_savepoints feature. But I leave this for another ticket.