I am getting this error "Source array was not long enough. Check the source index, length, and the array's lower bounds. (Parameter 'sourceArray')" whenever I'm scanning files larger than 20mb. If the file is larger than 20mb it should be split into 20mb chunks but there seem to be a problem with it. Here's the code:
public async Task ScanDocument(Document document)
{
try
{
var containerName = document.LookupAVScanResultTypeId == (int?)AVScanResultType.Infected ?
_documentationMaliciousContainerName :
_documentationContainerName;
if (!await _blobStorageService.ContainerExistsAsync(containerName))
{
_logger.LogInformation("Blob container could not be found: {ContainerName}", containerName);
return;
}
var srcBlob = await _blobStorageService.GetFileAsStreamAsync(document.BlobFileName, containerName);
var validationResult = _fileUploadValidator.Validate(document.Name, srcBlob, false);
if (validationResult.HasErrors)
{
document.UpdateAVScanResult((int)ClamScanResults.Error, string.Empty);
var errorMessage = string.Join(",", validationResult.Errors.Select(e => e.ErrorMessage));
errorMessage = string.Format(errorMessage, AVScanConstants.ScanUploadErrorMessage);
_logger.LogError("{ErrorMessage}", errorMessage);
return;
}
ClamScanResult scanResult = new ClamScanResult("Clean");
var fileSize = srcBlob.Length;
// if fileSize > 20 MB - then scan it in chunks of 20MB
if (fileSize > 20000000)
{
var chunks = (fileSize / 20000000) + 1;
ClamScanResult finalScanResult = new ClamScanResult("Clean");
byte[] fileBytes = new byte[srcBlob.Length];
using (var ms = new MemoryStream())
{
// get file bytes
await srcBlob.CopyToAsync(ms);
fileBytes = ms.ToArray();
}
for (int i = 0; i < chunks; i++)
{
// if on last chunk
if (i == chunks - 1)
{
// get last chunk of bytes
var lastChunkSize = fileSize - (i * 20000000);
byte[] chunkedBytes = new byte[lastChunkSize];
Array.Copy(fileBytes, (i * 20000000), chunkedBytes, 0, lastChunkSize);
// scan last chunk of bytes
scanResult = await _clamClient.SendAndScanFileAsync(chunkedBytes);
}
else // not on last chunk yet
{
// get chunked bytes
byte[] chunkedBytes = new byte[20000000];
Array.Copy(fileBytes, (i * 20000000), chunkedBytes, 0, 20000000);
// scan chunk of bytes
scanResult = await _clamClient.SendAndScanFileAsync(chunkedBytes);
if (scanResult.Result == ClamScanResults.VirusDetected)
{
// virus detected, stop iterating and return virus detected
break;
}
}
}
}
else // if file size below 20MB
{
scanResult = await _clamClient.SendAndScanFileAsync(srcBlob);
}
if (scanResult.Result == ClamScanResults.VirusDetected)
{
document.VirusName = scanResult.InfectedFiles?.First()?.VirusName;
_logger.LogInformation("Virus found in file {BlobFileName}", document.BlobFileName);
_logger.LogInformation("Virus name: {VirusName}", document.VirusName);
_logger.LogInformation("Handling Scan Results - {ScanResult}", scanResult);
await _avScanService.Remediate<Document>((int)scanResult.Result, document.BlobFileName);
}
else if (scanResult.Result == ClamScanResults.Unknown || scanResult.Result == ClamScanResults.Error)
{
_logger.LogError("Error scanning file: {RawResult}", scanResult.RawResult);
}
else
{
using var ms = new MemoryStream();
srcBlob.Position = 0;
await srcBlob.CopyToAsync(ms);
var fileBytes = ms.ToArray();
var invalidExcelFormulaKeywords = _configSettingService.GetSetting(ConfigSettingKeys.InvalidExcelFormulaKeywords)?.Split(",");
var (hasUpdate, updatedFileBytes) = _secureExcelFile.EscapeCellsWithInsecureValue(invalidExcelFormulaKeywords, fileBytes, document.Name);
if (hasUpdate)
{
await _avScanService.UpdateBlobFile<Document>(new MemoryStream(updatedFileBytes), document.BlobFileName);
}
}
document.LookupAVScanResultTypeId = (scanResult.Result == ClamScanResults.VirusDetected
|| scanResult.Result == ClamScanResults.Clean) ?
(int)scanResult.Result : (int)ClamScanResults.Error;
document.LastScannedDate = DateTime.UtcNow;
}
catch (Exception ex)
{
document.LookupAVScanResultTypeId = (int)ClamScanResults.Error;
document.LastScannedDate = DateTime.UtcNow;
_logger.LogError(ex, AVScanConstants.ScanUploadErrorMessage);
}
}