Pointer Checker may not work with un-dimensioned array in the presence of dynamic library.

Reference number: DPD200358286.

Product Version:

  • Intel® Parallel Studio 2013.
  • Intel® Parallel Composer XE 2013
  • Intel® Parallel Composer XE 2015

Operating Systems: Linux*

Problem Description:

For un-dimensional array such as: extern int myInt[]; the Intel C++ compiler has no way to get the upper bound from this declaration for variable myInt.  In such case it creates an external __cp_array_end_myInt that points to 1 past the last byte allocated to myInt.

In the module where myInt is defined as: int myInt[50]; it will follow the symbol entry for myInt in the same section and attributes of __cp_array_end_myInt.

There is no problem if myInt is defined in the same executable as it is used.  But if myInt is defined in a shared library, the shared library will see the two symbols in the expected position and get the correct value for the upper bound, but another executable linked to the shared library will not. The problem is that when the linker loads the symbols from the shared library, it doesn’t preserve the relative ordering of the symbols.
For example:

$ cat myshared.c
typedef struct _TestStruct {
    const char *pAChar;
    int myInt;
    long myLong;
} TestStruct;

const TestStruct kk_myVar[] =  {
    { (const char *)"string1", 10, (long)0},
    { (const char *)"string2", 20, (long)0},
    { (const char *)"string3", 30, (long)0},
    { (const char *)"string4", 40, (long)0},
    { (const char *)0, (int)0, (long)0}
};

$ cat main.c
typedef struct _TestStruct {
    const char *pAChar;
    int myInt;
    long myLong;
} TestStruct;

int main() {
    printf ("myInt is: %d\n", kk_myVar[0].myInt);
    return 0;
}

$ icc –c –g –O2 –check-pointers=rw –fPIC –w myshared.c
$ icc –c –g –O2 –check-pointers=rw main.c
$ icc -shared -o libDynamic.so myshared.o
$ icc -o test_dynamic main.o –L. -lDynamic -check-pointers=rw
$ nm libDynamic.so |grep kk_myVar
00000000002009d8 D __cp_array_end_kk_myVar (x2009d8 is an upper bound value of kk_myVar)
0000000000200960 D kk_myVar  (x200960  is a lower bound value of kk_myVar)

As you can see the size of kk_myVar is 120 bytes.

$ nm test_dynamic |grep kk_myVar
0000000000603840 B __cp_array_end_ kk_myVar(x603840 is an upper bound value of kk_myVar)
0000000000603860 B kk_myVar (x603860 is a lower bound value of kk_myVar)

The size of kk_myVar is negative 32. So Pointer Checker reports a false positive in main.c:

$ ./test_dynamic
CHKP: Bounds check error ptr=0x603868 sz=4 lb=0x603860 ub=0x60383f loc=0x400d76
Traceback:
    at address 0x400d76 in function main
    in file /working_dir/main.c line 11
    CHKP Total number of bounds violations: 1

Resolution Status:

We are aware of this issue and the compiler engineers are working on the fix right now. Once the fix is available, this article will be updated to include the information.

For now one simple workaround is to build everything including the executables in PIC/PIE mode. This causes the compiler to generate GOT-based relocations instead of the copy-relocations so avoiding the problem

For more complete information about compiler optimizations, see our Optimization Notice.