0

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);
        }
    }
  • Found the problem. It only shows the error if the file that is being scanned is a zipped file. Specially large zipped file (more than 20mb). I still can't figure out the proper solution for this. Hope someone helps. Thank you. – Doctorr0313 Oct 05 '22 at 12:59

0 Answers0