Federico Mariani created CAMEL-24104:
----------------------------------------

             Summary: camel-bean: racy lazy Processor-adapter lookup in 
AbstractBeanProcessor (non-volatile fields, no retry on conversion failure)
                 Key: CAMEL-24104
                 URL: https://issues.apache.org/jira/browse/CAMEL-24104
             Project: Camel
          Issue Type: Bug
          Components: camel-bean
    Affects Versions: 4.21.0
            Reporter: Federico Mariani


{{AbstractBeanProcessor.getCustomAdapter()}} lazily resolves a custom 
{{Processor}} adapter for the bean via type conversion, guarded by:

{code:java}
private transient Processor processor;
private transient boolean lookupProcessorDone;
...
Processor target = getProcessor();            // plain read, no lock
if (target == null) {
    if (allowCache) {
        if (!lookupProcessorDone) {           // plain read, no lock
            lock.lock();
            try {
                lookupProcessorDone = true;   // set BEFORE conversion
                target = ...tryConvertTo(Processor.class, exchange, beanTmp);
                processor = target;
            } finally { lock.unlock(); }
        }
    }
{code}

Two issues:

# {{lookupProcessorDone}} and {{processor}} are *non-volatile* and read outside 
the lock. A racing thread can observe {{lookupProcessorDone == true}} while 
still reading a stale {{null}} {{processor}} → that exchange silently falls 
back to bean-binding method invocation instead of the custom {{Processor}} 
adapter (different invocation semantics for that message). There is also no 
double-check of {{lookupProcessorDone}} after acquiring the lock, so two 
threads racing before the flag is visible both perform the conversion (benign, 
but shows the guard is not doing its job).
# {{lookupProcessorDone = true}} is set *before* {{tryConvertTo}}; if the 
conversion throws, the adapter lookup is permanently disabled without retry.

Suggested fix: make both fields {{volatile}} (or do the whole 
check-and-populate under the lock with a re-check), and set the flag after the 
conversion succeeds.

No test attached — the visibility race is not deterministically reproducible in 
a unit test; the defect is evident from the field declarations and access 
pattern in {{AbstractBeanProcessor.java}}.

_This issue was found by an AI-assisted code review. Reported by Claude Code on 
behalf of [~fmariani] (GitHub: Croway)._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to