public TransformationAddingJunkBytes(IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
                                      IInstructionWithAddressOperandTransform instructionWithAddressOperandTransform,
                                      ICodeInMemoryLayoutFactory codeInMemoryLayoutFactory,
                                      ICodeFactory codeFactory,
                                      IInstructionWithAddressOperandTransform jumpInstrucionTransform,
                                      ICodeTransform codeTransform,
                                      IStatistics statistics,
                                      IRelocationDirectoryFromNewCode relocationDirectoryFromNewCode,
                                      IJunkBytesProvider junkBytesProvider,
                                      IDisassemblerFactory disassemblerFactory) :
     base(instructionWithAddressOperandDecider, instructionWithAddressOperandTransform,
          codeFactory, codeInMemoryLayoutFactory, codeTransform, statistics,
          relocationDirectoryFromNewCode)
 {
     m_junkBytesProvider   = junkBytesProvider ?? throw new ArgumentNullException(nameof(junkBytesProvider));
     m_disassemblerFactory = disassemblerFactory ?? throw new ArgumentNullException(nameof(disassemblerFactory));
 }
        private bool TryGenerateJunkInstruction(IBasicBlock basicBlock,
                                                IJunkBytesProvider junkBytesProvider,
                                                IStatistics statistics,
                                                out IAssemblyInstructionForTransformation junkInstruction)
        {
            junkInstruction = null;
            bool retVal = false;

            //get junk bytes
            byte[] junkBytes = junkBytesProvider.GetJunkBytes();
            if (junkBytes == null)
            {
                throw new NullReferenceException(nameof(junkBytes));
            }

            //get basic block bytes
            byte[] basicBlockBytes = basicBlock.GetAllBytes();

            //the size of the junk we try to insert
            uint junkBytesSize = (uint)junkBytes.Count();

            //the inde of the most far insruction that has been syncronized
            uint mostFarSyncInstructionIdx = 0;
            //the partial instruction that causes the synchronization to be far as possible
            uint bestPartialInstructionSize = 0;

            //check what sub array of the inserted junk causes the most of confusion
            //so instruction are disassembled not correctly as far as possible
            while (junkBytesSize > 0)
            {
                uint   sizeOfNewBytesArray = basicBlock.NumberOfBytes + junkBytesSize;
                byte[] newBasicBlockBytes  = new byte[sizeOfNewBytesArray];

                //copy junk bytes and then basic block bytes
                Array.Copy(junkBytes, newBasicBlockBytes, junkBytesSize);
                basicBlockBytes.CopyTo(newBasicBlockBytes, junkBytesSize);

                //the index of first identical disassembled instruction to original
                uint?indexOfFirstIdenticalInstruction = CompareDisassembleToOriginal(newBasicBlockBytes, basicBlock,
                                                                                     m_disassemblerFactory);

                //in case that there is no even one instruction that synchronizes, so try another sequence
                //because the parsing error can not proceed to the next block
                if (!indexOfFirstIdenticalInstruction.HasValue)
                {
                    junkBytesSize--;
                    continue;
                }

                if (indexOfFirstIdenticalInstruction.Value > mostFarSyncInstructionIdx)
                {
                    mostFarSyncInstructionIdx  = indexOfFirstIdenticalInstruction.Value;
                    bestPartialInstructionSize = junkBytesSize;
                }

                junkBytesSize--;
            }

            //update basic block with the instruction that causes the synchronization to be as far as
            //possible
            if (mostFarSyncInstructionIdx > 0)
            {
                byte[] junkBytesSelected = new byte[bestPartialInstructionSize];
                for (int i = 0; i < bestPartialInstructionSize; i++)
                {
                    junkBytesSelected[i] = junkBytes[i];
                }

                var disasm = m_disassemblerFactory.Create(junkBytesSelected);
                junkInstruction       = disasm.Disassemble().First();
                junkInstruction.IsNew = true;

                statistics.IncrementMissinterpretedInstructions(mostFarSyncInstructionIdx);
                statistics.IncrementJunkInstructions(1, (uint)junkInstruction.Length);
                retVal = true;
            }

            return(retVal);
        }