It seems substr assumes the whole string tail must be returned when the last argument is zero:
terraform console
> substr("abc", 0, 0)
abc
> substr("abc", 1, 0)
bc
This behavior isn't described in the documentation; moreover, it seems this can lead to a number of issues when the length of a substring is computed rather than pre-defined.