Seems that output (or counter) for table record count uses 4 byte integer instead of 8 byte integer, and also uses signed integer.
For example, statistics of the table where there are ~3.7 billion records - it is shown as negative value

If this value is converted to hex, and then back to decimal as unsighed, it will be 3720051796 which is close to real record count number. Anyway, 4 byte integer, even unsigned, is not enough, because Firebird 2.x have 48 bit record number limit, not 32bit.

p.s. please, also check GSTAT for other places where overflow can happen, for example, if any index will be created on that table number of nodes (keys) also may be shown incorrectly, if wrong variables are used for that numbers.

Description

Seems that output (or counter) for table record count uses 4 byte integer instead of 8 byte integer, and also uses signed integer.
For example, statistics of the table where there are ~3.7 billion records - it is shown as negative value
ORDER_LINE (136)
Primary pointer page: 156, Index root page: 157
Average record length: 60.09, total records: -574915500
Average version length: 0.00, total versions: 0, max versions: 0
Data pages: 22958125, data page slots: 22958125, average fill: 76%
Fill distribution:
0 - 19% = 0
20 - 39% = 0
40 - 59% = 1
60 - 79% = 22958124
80 - 99% = 0
If this value is converted to hex, and then back to decimal as unsighed, it will be 3720051796 which is close to real record count number. Anyway, 4 byte integer, even unsigned, is not enough, because Firebird 2.x have 48 bit record number limit, not 32bit.
p.s. please, also check GSTAT for other places where overflow can happen, for example, if any index will be created on that table number of nodes (keys) also may be shown incorrectly, if wrong variables are used for that numbers.