Recursion (or rather reentrancy) detection won't do. It's not only about odd code that fiddles with call outs from operators: Since a thread switch can occur anywhere in pike code, it could cause random failures in unrelated code in other threads.
There's not much that can be done against bad hashing if the same function is added a gazillion times, I guess. But otoh the large buckets don't matter except in the specific code you mentioned, right?
Performance aside, it's not good that it can consume an unbounded amount of svalue stack either. At the very least there should be a check_stack() in there somewhere.
I don't see any easy way of getting rid of the loop that copies the whole bucket. But something that ought to mitigate most of the problem would be to only push functions that aren't is_identical to each other, because is_eq should never behave differently for them (we can safely ignore silliness like random() in `==). I reckon simply comparing with the previous entry on the stack should be good enough.