This is an archive of the discontinued LLVM Phabricator instance.

Add a limit to __make_integer_seq builtin.
Needs ReviewPublic

Authored by erichkeane on Oct 27 2021, 1:27 PM.

Details

Summary

As brought up in PR48246, passing a large value to __make_integer_seq
results in the compiler getting stuck in a large loop and potentially
crashing if it runs out of memory as a result.

This patch puts a command-line configurable limit in place to limit the
size to something reasonable.

I chose 2^24 as default after a brief experimentation with the debug compiler,
which made it take a few minutes. On a release build, a program with a 2^24
value takes roughly 30 seconds, and uses about 3.3GB of ram.

Diff Detail

Event Timeline

erichkeane created this revision.Oct 27 2021, 1:27 PM
erichkeane requested review of this revision.Oct 27 2021, 1:27 PM

Some additional data on a release build (on my quite recent Xeon 8260M):
2^24: 27 sec, ~3.3GB
2^25: 49 sec, ~6.4GB

It follows a pretty linear pattern from there. I'm open to choosing a different limit if we find one more reasonable for some reason or another (@ldionne opinion?).

rsmith added a subscriber: rsmith.EditedOct 27 2021, 2:10 PM

I wonder if more generally we should have a limit on either the size of a pack or the number of template arguments in a template specialization, rather than limiting only __make_integer_seq? I think a hand-rolled make_integer_sequence implementation should also be limited in the same way. Eg: https://godbolt.org/z/Yhb6E4vTG

I'd also be inclined to pick a smaller default limit for the more general constraint. Maybe 64K? I think we should be aiming to pick a limit that causes template argument list explosions to be caught before the compiler runs out of memory and dies and before the user gets bored and interrupts the compilation, and 16M seems a bit high for both. For the above example, we take 6s on godbolt for 64K, and ~30s for 512K.

I wonder if more generally we should have a limit on either the size of a pack or the number of template arguments in a template specialization, rather than limiting only __make_integer_seq? I think a hand-rolled make_integer_sequence implementation should also be limited in the same way. Eg: https://godbolt.org/z/Yhb6E4vTG

That seems like a reasonable error, I agree. I looked into the number of template arguments in a specialization, however, i've been looking through all the places that TemplateArgumentListInfo::addArgument is called, and it seems that we do this kind of all over the place... I would imagine we would want to catch this as we are adding, since if we wait until after (when it is converted to a ASTTemplateArgumentListInfo or something), the damage has already been done, right?

Or am I taking this too literally?

I'd also be inclined to pick a smaller default limit for the more general constraint. Maybe 64K? I think we should be aiming to pick a limit that causes template argument list explosions to be caught before the compiler runs out of memory and dies and before the user gets bored and interrupts the compilation, and 16M seems a bit high for both. For the above example, we take 6s on godbolt for 64K, and ~30s for 512K.

I don't mind a 64k default, I was concerned with what I did (16 million) being too small of a limit, but I don't have a good idea of the scale of what library folks end up doing for this.