Bug description
When using the ClamAV daemon (socket) mode instead of the clamscan executable,
file uploads always fail with "ClamAV was unable to complete its scan of this
file", even when clamd is running correctly and reachable.
Root cause
In ClamavPlugin.php, the _clamDaemonShortPolling() method has the
throw new ClamScanFailureException(...) statement placed inside the
polling for loop, right after the if ($output !== "") check, instead of
after the loop:
for ($i = 0; $i < $intervals; $i++) {
time_nanosleep(0, $delay);
$output = stream_get_contents($socket);
if ($output !== "") {
// ... returns result
}
throw new ClamScanFailureException("ClamAV failed to scan the file"); // <-- BUG
}
Because of this, the method throws an exception on the very first
iteration if clamd hasn't responded yet (which is almost always the case,
since scanning takes some milliseconds), instead of actually retrying up to
clamavSocketTimeout seconds as intended. The daemon connection itself works
fine — this is purely a control-flow bug that defeats the polling logic
entirely.
Fix
Move the throw statement outside the for loop, so it only fires after
all intervals have been exhausted without a response:
for ($i = 0; $i < $intervals; $i++) {
time_nanosleep(0, $delay);
$output = stream_get_contents($socket);
if ($output !== "") {
// ... returns result
}
}
throw new ClamScanFailureException("ClamAV failed to scan the file");
Environment
- OJS 3.3.x on Windows Server (WAMP stack)
- clamd 1.5.2, TCP socket mode (127.0.0.1:3310)
- Confirmed the daemon connection itself works correctly via a standalone
stream_socket_client() test script — the plugin's polling logic was the
only issue.
Bug description
When using the ClamAV daemon (socket) mode instead of the clamscan executable,
file uploads always fail with "ClamAV was unable to complete its scan of this
file", even when clamd is running correctly and reachable.
Root cause
In
ClamavPlugin.php, the_clamDaemonShortPolling()method has thethrow new ClamScanFailureException(...)statement placed inside thepolling
forloop, right after theif ($output !== "")check, instead ofafter the loop:
Because of this, the method throws an exception on the very first
iteration if clamd hasn't responded yet (which is almost always the case,
since scanning takes some milliseconds), instead of actually retrying up to
clamavSocketTimeoutseconds as intended. The daemon connection itself worksfine — this is purely a control-flow bug that defeats the polling logic
entirely.
Fix
Move the
throwstatement outside theforloop, so it only fires afterall intervals have been exhausted without a response:
Environment
stream_socket_client()test script — the plugin's polling logic was theonly issue.