ice_cube icon indicating copy to clipboard operation
ice_cube copied to clipboard

Infinite loop when invoking #first

Open jorgemanrubia opened this issue 2 years ago • 1 comments

This enters an infinite loop:

schedule = IceCube::Schedule.new(Time.current) do |schedule|
  schedule.add_recurrence_rule IceCube::IcalParser.rule_from_ical("FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=31;BYMONTH=2")
end
schedule.first(2) # hangs!

We have patched this internally with:

module ValidatedRuleWithInfiniteRecursionGuard
  private
    MAX_LOOPS = 10_000

    def find_acceptable_time_before(boundary)
      count = 0
      until finds_acceptable_time? || count > MAX_LOOPS
        return false if past_closing_time?(boundary)
        count += 1
      end
      true
    end
end

IceCube::ValidatedRule.prepend(ValidatedRuleWithInfiniteRecursionGuard)

I'm happy to submit a fix to the library. It could be the specific patch suggested above, but the several loop and until usages inside the library, combined with the complex logic, looks like a liability. I think a better patch would be to replace the current loop and until usages with safe_ versions that control a max number of iterations to prevent these infinite loops by design. For example:

safe_loop do # m = 10_000 or whatever by default, and can be passed by parameter 
end

What do you think?

Similar to https://github.com/ice-cube-ruby/ice_cube/issues/469

jorgemanrubia avatar Jan 19 '24 20:01 jorgemanrubia

I think it's probably better to ensure the rule is valid, rather than break out of an infinite loop. Although, it would obviously be better to gracefully handle an infinite loop than crash.

For example, #554 will fix the issue raised in #469, but does not handle infinite loops.

pacso avatar May 10 '24 20:05 pacso