Memory overwrite using BinarySearch on x64 server with 4Gb of ram

G

Guest

Changing the List<T>. BinarySearch to use my own implementation fixes the
problem. And I am not getting it to fail on my x86 machine.

It fails in release on several Dell 1425 with Win2003 x64 with the Exception:

Unhandled Exception: System.InvalidOperationException: Failed to compare two
elements in the array. ---> System.AccessViolationException: Attempted to
read or write protected memory. This is often an indication that other memory
is corrupt.

Here the code the makes it crach and the test data can be found here:
http://myportal.cyberwatcher.com/WordDictionary.rar

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace MemoryOverwrite
{
public sealed class WordDictionary
{
static readonly WordDictionary _instance = new WordDictionary();
public static WordDictionary Instance
{
get { return _instance; }
}

List<Word> _dictionaryAsList = new List<Word>(1000000);

private WordDictionary()
{ }

public Word Find(string word)
{
if (word.Length > 250) word = word.Substring(0, 250);

Word toFind = new Word(word);
int index = _dictionaryAsList.BinarySearch(toFind, new
Word.WordComparer());
if (index >= 0) return _dictionaryAsList[index];
else return toFind;
}

/// <summary>
/// Usulay craches after 3-5 iterations with:
///
/// Unhandled Exception: System.InvalidOperationException: Failed to
compare two elements in the array.
/// ---> System.AccessVilationException: Attempted to read or write
protected memory.
/// This is often an indication that other memory is corrupt.
/// </summary>
public void MakeItCrachOn64Bit()
{
for (int i = 0; ; i++)
{
foreach (Word word in _dictionaryAsList)
{
string text = word.Text;
Word word2 = Find(text);
}
Console.WriteLine("{0}", i);
}
}

public void Load()
{
string file = @"WordDictionary.bin";
if (!File.Exists(file)) return;
Stream st = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(st, Encoding.UTF8);

int version = reader.ReadInt32();
int cnt = reader.ReadInt32();
int lastLocalDocIdFromDictionaryFile = reader.ReadInt32();
reader.BaseStream.Position = 100;

_dictionaryAsList = new List<Word>(cnt);
for (int i = 0; i < cnt; i++)
{
Word word = new Word(reader);
_dictionaryAsList.Add(word);
}
if (st.Length != st.Position) Console.WriteLine("st.Length !=
st.Position");
reader.Close();
}

}

public struct Word
{
byte[] _data;

public class WordComparer : IComparer<Word>
{
public int Compare(Word lhs, Word rhs)
{
return string.Compare(lhs.Text, rhs.Text,
StringComparison.Ordinal);
}
}

public Word(string text)
{
_data = Init(text);
}

static byte[] Init(string text)
{
byte[] textData = UTF8Encoding.UTF8.GetBytes(text);
int length = textData.Length;
if (length > 255) throw new Exception("length > 255");
byte[] data = new byte[1 + length];
data[0] = (byte)length;
Array.Copy(textData, 0, data, 1, length);
return data;
}

public Word(BinaryReader reader)
{
string text = reader.ReadString();
int id = reader.ReadInt32();
int cnt = reader.ReadInt32();
uint pos = reader.ReadUInt32();

_data = Init(text);
}

public string Text
{
get
{
return UTF8Encoding.UTF8.GetString(_data, 1, _data[0]);
}
}
}
}


-Rune Lind
 
G

Guest

I forgot the program to run it:

using System;
using System.Collections.Generic;
using System.Text;

namespace MemoryOverwrite
{
class Program
{
static void Main(string[] args)
{
WordDictionary.Instance.Load();
WordDictionary.Instance.MakeItCrachOn64Bit();
}
}
}

It usually crashes after 2-3 minutes...

- Rune
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top