shashank created CAMEL-26311:
--------------------------------
Summary: camel-core-languages - Simple: a predicate inside ${ }
with equals, !equals, !startsWith or !endsWith, or with a quoted argument on
the left, is not read as a predicate: ${header.type equals 'gold'} never
matches, ${uppercase('a') == 'B'} always matches
Key: CAMEL-26311
URL: https://issues.apache.org/jira/browse/CAMEL-26311
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
Assignee: shashank
Since CAMEL-24921 (4.23.0) the braces may hold a predicate: {{${header.n > 0}}}
is read as {{${header.n} > 0}}. {{SimpleSyntaxHints.operatorsOutside}} decides
whether the text inside the braces is a predicate; when it answers null the
text is read as one function (main aa63c0a4cb94, also 4.23.0). It answers null
in two cases where the text is a predicate:
# The operators {{equals}}, {{!equals}} (CAMEL-24582), {{!startsWith}} and
{{!endsWith}} (CAMEL-22868) are not in its list of operator words ({{equals}}
and {{!equals}} are also missing from the list {{wrapComparison}} uses). The
text is then one header name:
{code}
${header.type equals 'gold'} -> null as an expression; a predicate that
never matches (header type = gold)
${header.type !equals 'silver'} -> never matches
${header.type !startsWith 'si'} -> never matches
${header.type} equals 'gold' -> true (outside the braces: right)
{code}
# A quote anywhere before the operator makes it give up
({{head.contains("'")}}), so a function with a quoted argument on the left
loses the comparison: the function is created from {{uppercase('a')}} and the
rest, {{ == 'B'}}, is ignored:
{code}
${uppercase('a') == 'B'} -> A as an expression; a predicate
that always matches
${substringAfter('Hello ') == 'Camel'} -> matches for any body with text
after "Hello "
${uppercase(a) == 'B'} -> false (no quote: right)
${header.x == 'y' && uppercase('a') == 'B'} -> false (after && the comparison
is read: right)
{code}
The operator page says "An operator can be written inside ${ } or outside it
[...] Both mean the same thing" and lists these operators. In a {{filter}} or
{{choice}} the predicate is silently always false or always true: no error,
wrong routing.
*Fix* (proposed): add the four operators to both lists, and take the first
operator that is outside quotes, brackets and parentheses (the
{{indexOutsideQuotes}} helper of CAMEL-25954) instead of giving up when a quote
comes before it; the count of brackets and parentheses before the operator is
then not needed (it also counted those inside quotes, as in {{${replace('(',
'[') == 'Hi'}}}). An operator inside a quoted argument, as in {{${replace(' ==
','=')}}}, is still part of the argument, and {{${properties:msg:a == b}}},
{{${header[order in progress]}}} are unchanged. The condition of a ternary
inside the braces is wrapped with the same operator list, so {{${header.type
equals 'gold' ? 'a' : 'b'}}}, refused today, works too. The fix relies on
CAMEL-25954 (on main): only since then does {{indexOutsideQuotes}} skip
brackets and parentheses.
*Tests*: {{SimplePredicateInBracesTest}}:
{{testEveryComparisonOperatorInsideTheBraces}},
{{testFunctionWithAQuotedArgumentOnTheLeft}} and
{{testEqualsInTheConditionOfATernaryInsideTheBraces}} fail on main and pass
with the fix; {{testAnOperatorInsideQuotesIsPartOfTheArgument}} is a control.
The language tests of camel-core and the whole camel-core suite pass with the
fix. Every {{${ }}} text in apache/camel and camel-kamelets 4.23.0 (3 763
distinct) gets the same answer from {{operatorsOutside}} with and without the
fix.
*How it was found*: a readable semantics of Simple written from the
documentation (Rocq), extracted to an oracle and compared with the language on
about 4.9 million generated programs; this class gave 24 800 of the
disagreements. The decision of {{operatorsOutside}} is also checked on the real
class files of main and of the fix in a JVM model in Rocq (kernel-checked).
*Affected*: main, 4.23.x (CAMEL-24921; a backport there needs CAMEL-25954 too).
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)