Does this program make sense?

I see no reason this program would be considered invalid, and it ought to behave as you probably expect. That said, it is an unusual example/style, and is mixing several features not commonly seen together in ways that are redundant, so not surprised by any bugs you find in compilers with it.

For example, you could remove the allocatable attribute and allocate statement, and the program would likely work fine. This makes str2 an “automatic” variable.

On the other hand you could change len(str) in the declaration to :, and either omit the allocate statement (to get automatic allocation on assignment) or change it to allocate(character(len=len(str)) :: str2). This has become the more common way since this feature was introduced.