BUG: Incorrect Cast from Near to Far Function Pointer

ID: Q116243

7.00 | 1.00 1.50 MS-DOS | WINDOWS kbtool kbbuglist

The information in this article applies to:

SYMPTOMS

The code listed below should cause the compiler to return error message C2187: "Cast of near function pointer to far function pointer." Instead, incorrect code is generated that loads the segment of the far function pointer with DS, the data segment, rather than with the correct code segment.

CAUSE

This condition is not correctly caught in the initial stage and code generation continues, where the far function pointer is treated as a data address and the address is extended using the data segment.

RESOLUTION

There is no direct workaround, so assignments that convert near and far pointers to functions (function addresses) should be avoided. In addition, because the function is near, the return instruction generated is also near. If the function pointer is correctly cast to be far, both CS and IP are pushed on the stack during a function call. The near return only pops IP, causing stack corruption and causing execution to continue in an incorrect location.

STATUS

Microsoft has confirmed this to be a bug in the C/C++ compiler for MS-DOS, versions 7.0, 8.0, and 8.0c. We are researching this problem and will post new information here in the Microsoft Knowledge Base as it becomes available.

This problem does not occur in the 32-bit C/C++ compiler, because there are no near and far pointers in flat addressing.

MORE INFORMATION

The following sample code can be used to demonstrate this problem:

Sample Code

/* Compile options needed: /c /Gs /f- /Fc
*/ 

   #include <stdio.h>
   #include <dos.h>

   typedef void (__far *FARFUNCPTR)(void) ;
   typedef void (__near *NEARFUNCPTR)(void) ;

   void hfunc (void) { return; }
   FARFUNCPTR install (NEARFUNCPTR) ;

   FARFUNCPTR install (NEARFUNCPTR handler)  {
      return (FARFUNCPTR)handler;
   }

   int main (void) {

       FARFUNCPTR fptr ;

       printf("CS= %04x\nDS= %04x\n", __segname("_CODE"),
   __segname("_DATA"));
       fptr= install(hfunc);
       printf("Install %Fp\n", fptr);
       fptr= (FARFUNCPTR) hfunc ;
       printf("Direct %Fp\n",fptr);

       return (0);
   }

//This is the portion of the /Fc compiler listing that illustrates the
//incorrect use of DS as the segment of the far function pointer:

   ;|***      return (FARFUNCPTR)handler;
   ; Line 20
   *** 00001b     8b 46 04           mov     ax,WORD PTR
    [bp+4]     ;handler
   *** 00001e     8c da                mov     dx,ds
   *** 000020     e9 00 00           jmp     $EX221

Additional reference words: 1.00 1.50 7.00 8.00 8.00c KBCategory: kbtool kbbuglist KBSubCategory: CodeGen Keywords : kb16bitonly

Last Reviewed: July 23, 1997