views:

131

answers:

4

I've been trying run Insure++ with some scientific code and it reports many errors, although to be fair it officially does not support K&R C and I don't know what having a lot of K&R functions has done to its evaluation process. The C and C++ code it is testing is being run in a DLL invoked from a WPF application.

One error report that puzzles me is the following, which I'm confident is safe code but am trying to work out why it thinks is an error (it does work). I'd be interested if anyone has an insight into why this might be an error condition.

[MacImagePlot.c:984] **READ_OVERFLOW**
SetCursorQD(*GetCursorQD(watchCursor));

Reading overflows memory: GetCursorQD(watchCursor)

bbbbb
| 4 | 4 |
    rrrrr

Reading (r) : 0x5639d164 thru 0x5639d167 (4 bytes)
From block (b) : 0x5639d160 thru 0x5639d163 (4 bytes)
gWatchCursor, declared at WPFMacGraphics.cpp, 418

for some very simple code.

    typedef int Cursor;
    typedef Cursor* CursPtr;
    typedef CursPtr* CursHandle;
    CursHandle GetCursorQD (short cursorID);
    void SetCursorQD (const Cursor *crsr);
    enum {
    ....
     watchCursor =  4 
    };


    // file globals
    Cursor gWatchCursor=watchCursor;
    CursPtr gWatchCursorPtr = &gWatchCursor;

    CursHandle GetCursorQD (short cursorID)
    {
      if (cursorID==watchCursor)  // this is actually the only case ever called
        return &gWatchCursorPtr;
      return 0;
    }
A: 

I'm not familiar at all with the tools you're talking about, but have you verified that your GetCursorQD function is returning the pointer you expect and not NULL/0?

Perhaps something wonky happened with your enum definition for watchCursor (such as it being declared differently elsewhere, or it picking up a local variable instead of the enum).

SoapBox
It's a good question but yes I'm absolutely certain - I've tested it with additional assertions in place to guarantee that and the code is actually working.
Andy Dent
A: 

Like Soapbox, I am not familiar with Insure++.

But looking at the code, it is admittedly a bit confusing...so

That typedef makes CursHandle effectively a pointer to pointer to int...

  • CursHandle is a pointer of type CursPtr
  • CursPtr is a pointer of type Cursor
  • Cursor is typedef'd to type int

yet in the GetCursorQD, you are using a 'double address of' int? The reason I say 'double address' is the function is returning a address of gWatchCursorPtr (&gWatchCursorPtr) of type CursHandle, which in turn is a global variable which is a address of gWatchCursor (&gWatchCursor) which is of type Cursor.

Your definition of the return type for the function does not match up with the global variable name's typeof despite the typedef's...that's what my thinking is...

Hope this helps, Best regards, Tom.

tommieb75
Blame Apple!The typedefs and signatures are all standard Quickdraw (original Mac API) and I'm porting legacy code which for various reasons I need to leave as close to the original as possible. This particular line of code is repeated dozens of times.Note that in the line of code that Insure++ complains about, `SetCursorQD( *GetCursorQD(watchCursor) );` the CursHandle returned is dereferenced with a leading * thus converting it back to a CursPtr so it does satisfy the Cursor* parameter type of SetCursorQD.Thanks for taking the time to look.
Andy Dent
@Andy: No problem...huh...Apple are full of surprises...never knew I was deciphering Apple's code..Learnt something new there eh? :D
tommieb75
+1  A: 

I hate to say it but I suspect your problem is going to be the lack of some arcane function modifiers needed to ensure that data on the stack isn't getting munged when crossing the DLL boundary. I'd suggest writing a simple app that replicates the code but does it all in one module and see if Insure++ still detects an error. If it doesn't, get ready to wade through __declspec documentation.

Jherico
I'm sure there is a long and painful story behind your thinking ;-) I already wrote a simple pure Win32 GUI that invokes the DLL with some canned scenarios, for other debugging, and I'll consider merging them as you suggest.
Andy Dent
I just realised that the code which is generating the report IS within the same DLL as the functions it is invoking, so your interesting suggestion doesn't help here. I've written it off as a false positive.
Andy Dent
A: 

I assume that the following line is the Problem:

  if (cursorID==watchCursor) 
  • cursorID is defined as short (usually 2 Bytes)

  • watchCursor is part of a enum and thus of type int (4 Bytes on a 32Bit OS)

This actually is not a problem. The compiler will cast one of both parameters correctly, as far as the enum value will not exceed a 2 Byte range.

By my experience all static (as well as runtime-) code analysis tools report many false positives (i tried some of them). They of course help, but it takes quite a while to assert false positives from real bugs.

RED SOFT ADAIR