shashank created CAMEL-26753:
--------------------------------
Summary: KeyValueRepository - a very large TTL wraps around, so
the entry expires at once or is left out of keys()
Key: CAMEL-26753
URL: https://issues.apache.org/jira/browse/CAMEL-26753
Project: Camel
Issue Type: Bug
Components: camel-jcache, camel-caffeine, camel-core, camel-jpa,
camel-ehcache, camel-sql
Reporter: shashank
Assignee: shashank
{{MemoryKeyValueRepository}}, {{JdbcKeyValueRepository}},
{{JpaKeyValueRepository}}, {{EhcacheKeyValueRepository}} and
{{JCacheKeyValueRepository}} compute the expiry time of an entry as
{{System.currentTimeMillis() + ttl.toMillis()}} without an overflow check. For
a TTL near {{Long.MAX_VALUE}} milliseconds, such as
{{Duration.ofMillis(Long.MAX_VALUE)}}, the sum wraps around to a negative time:
* {{MemoryKeyValueRepository}}, {{EhcacheKeyValueRepository}} and
{{JCacheKeyValueRepository}} treat the entry as expired at once: {{get}}
returns {{null}} right after {{put}}, and {{putIfAbsent}} overwrites it.
* {{JdbcKeyValueRepository}} and {{JpaKeyValueRepository}}, where an expiry
time of 0 means no expiry, return the value from {{get}} and {{contains}}, but
leave the entry out of {{keys()}} and {{size()}}. With the open fix for
CAMEL-26737, {{replace}} and {{delete(key, expected)}} of
{{JdbcKeyValueRepository}} also treat it as expired.
A TTL above {{Long.MAX_VALUE}} milliseconds, such as
{{ChronoUnit.FOREVER.getDuration()}}, makes {{Duration.toMillis()}} throw an
{{ArithmeticException}} from {{put}}, {{putIfAbsent}} and {{replace}}.
{{CaffeineKeyValueRepository}} calls {{ttl.toNanos()}}, which throws an
{{ArithmeticException}} already for a TTL of about 292 years.
The state store {{ttl}} option and {{CamelStateStoreTtl}} header, and the Cache
EIP {{ttl}}, are milliseconds passed as {{Duration.ofMillis(ttl)}}, so a user
who sets {{Long.MAX_VALUE}} to mean "forever" gets an entry that the in-memory
repository drops at once.
Found while fixing CAMEL-26737.
*Expected*: the {{KeyValueRepository}} Javadoc says that a null, zero or
negative TTL means no expiry; a positive TTL too large to add to the current
time should mean that the entry does not expire either, not that it expires at
once.
*Suggested fix*: add the TTL with {{Math.addExact}} and use {{Long.MAX_VALUE}}
when the sum or {{toMillis()}} overflows, in a shared helper in
{{KeyValueRepositoryHelper}}; in {{CaffeineKeyValueRepository}}, use
{{Long.MAX_VALUE}} nanoseconds when {{toNanos()}} overflows.
*Affected*: main and 4.23.0 (read, not run on 4.23.0; reproduced with unit
tests on main).
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)