Skip to content

Assignment to function pointers with checked and unchecked pointer arguments #664

Open
@secure-sw-dev-bot

Description

@secure-sw-dev-bot

This issue was copied from checkedc/checkedc-clang#668


In checked-c ideally, we would want an assignment to function pointers to follow function subtyping rules.

i.e.,

T1 f;
T2 fptr = f;

Where fptr is a function pointer of type T2 and f is a function of type T1.
The above assignment is valid iff T1 <: T2 according to function subtyping rules.

However, this is not the case.

More detailed example:

int * aptr(_Ptr<int> a, int *b);
int * bptr(int *a, _Ptr<int> b);
int* retptr(int *a, int *b): itype(_Ptr<int>);
int * abptr(_Ptr<int> a, _Ptr<int> b);

int main() {
   // This is a function pointer to a function that
   // accepts two checked pointers and return a
   // wild pointer.
   // i.e., all callers using this function pointer
   // will pass checked pointers as the two arguments
   // and treat the return value as WILD.
   _Ptr<int* (_Ptr<int> , _Ptr<int> )> b =  0;
   // This should be fine, because it only needs
   // first argument as checked pointer.
   // int* (_Ptr<int> , int* )  <: int* (_Ptr<int> , _Ptr<int> )
   b = aptr;
   // Similar to the above reasoning, this should be fine.
   b = bptr;
   // this is also fine because it expected no checked arguments
   // but could return checked type as its return.
   // int* (int*, int*) : itype(_Ptr<int>)  <: int* (_Ptr<int> , _Ptr<int> )
   b = retptr;
   // this is the true match.
   b = abptr;
   return 0;
}

However, the current version of clang throws an error.

When we try to compile the above source file using checkedc-clang, we get the following error:

error: assigning to '_Ptr<int *(_Ptr<int>, _Ptr<int>)>' from incompatible type 'int *(_Ptr<int>, int *)': type mismatch at 2nd parameter ('_Ptr<int>' vs 'int *')
   b = aptr;
     ^ ~~~~
funcptrbug.c:19:6: error: assigning to '_Ptr<int *(_Ptr<int>, _Ptr<int>)>' from incompatible type 'int *(int *, _Ptr<int>)': type mismatch at 1st parameter ('_Ptr<int>' vs 'int *')
   b = bptr;
     ^ ~~~~
funcptrbug.c:23:6: error: assigning to '_Ptr<int *(_Ptr<int>, _Ptr<int>)>' from incompatible type 'int *(int *, int *) : itype(_Ptr<int>)': type mismatch at 1st parameter
      ('_Ptr<int>' vs 'int *')
   b = retptr;
     ^ ~~~~~~
3 errors generated.

This seems to be consistent with the specification (Page 51, Section 3.8), i.e., function pointers types have to be an exact match, i.e., all the parameters and return types should have the same checked types.

I have the following concerns here:

  • This is non-intuitive, should this be changed?
  • Is there any rationale on not changing this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions