Invalid Floating Point Operation

D3X picture D3X · Nov 26, 2015 · Viewed 11.9k times · Source

I keep getting this error "Invalid Floating Point Operation".

I'm on Delphi 7.

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
TlHelp32, Dialogs, StdCtrls, ExtCtrls, Buttons, ComCtrls;

var //global
PHandle, cancel, bytes, scantype: integer;

...

procedure Tmain.scanbtnClick(Sender: TObject);
    var max, address: Integer;
    floatinput, floatinput1, floatinput2, datafloat: Real;
    x: cardinal;
    itm: TListItem;
begin

  floatinput := StrToFloat(Trim(valueinput.Text));
  floatinput1 := StrToFloat(Trim(valueinput1.Text));
  floatinput2 := StrToFloat(Trim(valueinput2.Text));

  if floatinput2 < floatinput1 then
  begin
    floatinput1 := floatinput1 + floatinput2;
    floatinput2 := floatinput1 - floatinput2;
    floatinput1 := floatinput1 - floatinput2;
  end;

  result.Show;

  x := 0;
  address := 0;

  result.resultlist.Clear;

  repeat
    Application.ProcessMessages;
    statusbar1.Panels.Items[1].Text := 'Searching... ' + IntToStr(address * 100 div max) + '% (' + IntToStr(address div bytes) + ' out of ' + IntToStr(max div bytes) + ').';

    if ReadprocessMemory(PHandle, Ptr(address), @datafloat, bytes, x) then
      begin
        if (x > 0) then
        begin
          if scantype = 0 then
          begin
            if datafloat = floatinput then             //error here
            begin
              itm := result.resultlist.Items.Add;
              itm.Caption := '0x' + IntToHex(address,8);
              itm.SubItems.Add(FormatFloat('0.0#########', datafloat));
            end;
          end;
          if scantype = 1 then
          begin
            if datafloat > floatinput              //also here
            then begin
              itm := result.resultlist.Items.Add;
              itm.Caption := '0x' + IntToHex(address,8);
              itm.SubItems.Add(FormatFloat('0.0#########', datafloat));
            end;
          end;
          if scantype = 2 then
          begin
            if datafloat < floatinput     //here too
            then begin
              itm := result.resultlist.Items.Add;
              itm.Caption := '0x' + IntToHex(address,8);
              itm.SubItems.Add(FormatFloat('0.0#########', datafloat));
            end;
          end;
          if scantype = 2 then
          begin
            if (dataint <= intinput2) and (dataint >= intinput1)    //even here
            then begin
              itm := result.resultlist.Items.Add;
              itm.Caption := '0x' + IntToHex(address,8);
              itm.SubItems.Add(FormatFloat('0.0#########', datafloat));
            end;
          end;

        end;
      end;

    if x <> 0
    then address := address + x
    else address := address + bytes;

  until (address >= Max) or (cancel = 1);

end;

I even checked on the cpu window, and it happens because its trying to load a floating point value from a pointer that is pointing at a null value.

It's not the ReadMemory, because this little piece of code is on a while loop and it returns several valid values before running into this error.

What should I do?

Thanks in advance.

Answer

David Heffernan picture David Heffernan · Nov 27, 2015

There are two potential problems with the code that we can see.

First of all you do not check the return value of ReadProcessMemory. That call could fail for a variety of reasons. Since you don't check for errors you have no way of knowing whether or not the function call succeeded. Always check API calls for success. Read the docs on MSDN to find out how to do so. Usually this involves checking the function return value, as is the case here. If the function fails, then the floating point variable may contain uninitialized data and an error may ensue.

The other problem is that datafloat is being populated by reading bytes from another process. If those bytes do not represent a valid floating point value, then an exception will be raised if you try to operate on that value. Not all bit patterns represent valid floating point values. For instance, you may have hit upon a signaling NaN value. Perhaps you should be comparing with a CompareMem given that you appear to be reading arbitrary memory in what looks like an effort to reverse engineer some other program. Testing by bitwise comparison will avoid the risk of loading invalid values into floating registers.

Finally, I'm not sure what you mean by testing a floating point value against null, whatever null is. Floating point values are not nullable. It is very likely that you have a significant misunderstanding there.