Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling function pointer bounds #587

Merged
merged 4 commits into from
Jun 18, 2021
Merged

Handling function pointer bounds #587

merged 4 commits into from
Jun 18, 2021

Conversation

Machiry
Copy link
Collaborator

@Machiry Machiry commented May 12, 2021

  • Make it explicit to not handle bounds for parameters of function pointers.
  • Fix writing of bounds to parameters of function pointers.

Issue: #575

@Machiry Machiry linked an issue May 12, 2021 that may be closed by this pull request
@mattmccutchen-cci
Copy link
Member

@Machiry This change may stop John's particular example from crashing 3C, but I wouldn't be surprised if there are other places that 3C can dereference a null ProgramVar given that it has already happened twice (#523 and #575). Can you explain more generally under what conditions a ProgramVar is allowed to be null and how the code is intended to prevent null dereferences so we can try to fix more of the problems now rather than later?

@Machiry
Copy link
Collaborator Author

Machiry commented May 13, 2021

@Machiry This change may stop John's particular example from crashing 3C, but I wouldn't be surprised if there are other places that 3C can dereference a null ProgramVar given that it has already happened twice (#523 and #575). Can you explain more generally under what conditions a ProgramVar is allowed to be null and how the code is intended to prevent null dereferences so we can try to fix more of the problems now rather than later?

ProgramVar is an object for each program variable (pointers and non-pointers) maintained by array bounds inference code. Array bounds code works with BoundsKey (unique id for all entities involved in bounds inference).

Ideally, all Boundskeys should have corresponding ProgramVar. However, there are certain cases where this is not the case. It is hard to anticipate these cases because of the crazy C syntax.
IMO, a reasonable approach is to fix these null-ptr issues as they come.

@john-h-kastner
Copy link
Collaborator

The total number of calls to getProgramVar is fairly low (22 according to clion). Could it make sense to just add a null check on all of them? The concern I suppose would be that this silently swallows an error in bounds inference that caused the program var to be absent in the first place.

@mattmccutchen-cci
Copy link
Member

The total number of calls to getProgramVar is fairly low (22 according to clion). Could it make sense to just add a null check on all of them? The concern I suppose would be that this silently swallows an error in bounds inference that caused the program var to be absent in the first place.

I suggest we make this a warning; then if we notice incorrect behavior later, we'll see the warning as a possible cause. If we later make it a priority to fix problems of this nature, we could run whatever tests we want with the warning temporarily changed to an error (via a command-line flag or just editing the code on a branch). This case with getProgramVar may be a good opportunity to set up a convenient mechanism that we can use in similar situations in the future.

@Machiry
Copy link
Collaborator Author

Machiry commented May 29, 2021

The total number of calls to getProgramVar is fairly low (22 according to clion). Could it make sense to just add a null check on all of them? The concern I suppose would be that this silently swallows an error in bounds inference that caused the program var to be absent in the first place.

I suggest we make this a warning; then if we notice incorrect behavior later, we'll see the warning as a possible cause. If we later make it a priority to fix problems of this nature, we could run whatever tests we want with the warning temporarily changed to an error (via a command-line flag or just editing the code on a branch). This case with getProgramVar may be a good opportunity to set up a convenient mechanism that we can use in similar situations in the future.

I would rather not make this, getProgramVar returning NULL is not expected (except for few cases). Making this a warning could silently skip these and I do not feel comfortable with that. Let's see if we face another of these NULL pointer issues and then make it as a warning.

@mattmccutchen-cci
Copy link
Member

mattmccutchen-cci commented May 31, 2021

I discussed the general unreliability of the bounds inference code with Mike. It's not clear to us what we should do about it now, so we propose to proceed with this specific fix and we can revisit the general problem later. John, if you have other thoughts about the general problem, let us know. Otherwise, we need to decide whether John or I will review the PR on its own merits. I imagine John knows more, but at some point it may make sense for me to start learning.

Copy link
Collaborator

@john-h-kastner john-h-kastner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine. Mostly suggestion for comment improvements.

clang/lib/3C/AVarBoundsInfo.cpp Outdated Show resolved Hide resolved
if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) {
if (PD->getParentFunctionOrMethod())
if (PD->getParentFunctionOrMethod()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this always be true now? isValidBoundVariable returns false when getParentFunctionOrMethod is null, so execution would never reach here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, No. isValidBoundVariable does not check for getParentFunctionOrMethod.

bool AVarBoundsInfo::isValidBoundVariable(clang::Decl *D) {
  // All parameters, return, and field values are valid bound variables.
  if (D && (isa<ParmVarDecl>(D) || isa<FunctionDecl>(D) || isa<FieldDecl>(D)))
    return true;
 
  // For VarDecls, check if these are are not dummy and have a name.
  if (auto *VD = dyn_cast_or_null<VarDecl>(D))
    return !VD->getNameAsString().empty();

  return false;
}

clang/lib/3C/AVarBoundsInfo.cpp Show resolved Hide resolved
clang/lib/3C/ConstraintVariables.cpp Outdated Show resolved Hide resolved
@mattmccutchen-cci

This comment has been minimized.

@mattmccutchen-cci mattmccutchen-cci removed their request for review June 16, 2021 01:15
@Machiry

This comment has been minimized.

Copy link
Collaborator

@john-h-kastner john-h-kastner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine to merge.

@Machiry Machiry merged commit a929d23 into main Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Null pointer derefence on function pointer parameter with bounds
3 participants