[cfe-dev] Static Checker: getting svals for a struct field value

McDowell, Raymond C. via cfe-dev cfe-dev at lists.llvm.org
Fri Jun 3 14:37:33 PDT 2016


To follow up on my own question, in case others have it later… Here’s what I did, that seems to be working:

  SVal BuffBase, BuffSize;
  MemRegionManager &MRMgr = St->getStateManager().getRegionManager();
  const TypedValueRegion *BuffReg = Buff.castAs<nonloc::LazyCompoundVal>().getCVData()->getRegion();
  const RecordType *BuffRTy = BuffReg->getValueType()->getAsStructureType();
  assert(BuffRTy && "Input buffer value is not a structure");
  const RecordDecl *BuffRD = BuffRTy->getDecl()->getDefinition();
  assert(BuffRD && "Input buffer structure has no definition");
  for (const auto *F : BuffRD->fields()) {
    if (F->getName() == "base") {
      BuffBase = St->getSVal(MRMgr.getFieldRegion(F, BuffReg));
   }
    else if (F->getName() == "size") {
      BuffSize = St->getSVal(MRMgr.getFieldRegion(F, BuffReg));
    }
  }

The above code sets BuffBase and BuffSize to be SVals for the field values in the structure SVal Buff.  To assign values to the fields (instead of reading their current values), I used code like the following:

  const VarRegion *BuffReg = Buff.getAsRegion()->getAs<VarRegion>();
  const RecordType *BuffRTy = BuffReg->getValueType()->getAsStructureType();
  assert(BuffRTy && "Output buffer value is not a structure");
  const RecordDecl *BuffRD = BuffRTy->getDecl()->getDefinition();
  assert(BuffRD && "Output buffer structure has no definition");
  for (const auto *F : BuffRD->fields()) {
    if (F->getName() == "size") {
      const FieldRegion *SizeFR = St->getStateManager().getRegionManager().getFieldRegion(F, BuffReg);
      St = St->bindLoc(loc::MemRegionVal(SizeFR), Size);
    }
  }

This changes the size field to have the value Size.


From: McDowell, Raymond C.
Sent: Friday, May 13, 2016 1:14 PM
To: 'Alexey Sidorin'; cfe-dev at lists.llvm.org
Subject: RE: [cfe-dev] Static Checker: getting svals for a struct field value

Thanks, Alexey, for your help.

Here’s a more detailed explanation of what I’m trying to do.  In our project we’ve created a struct type containing a pointer to a buffer and the size of the buffer (in bytes), so that we can pass these around together and not lose track of the buffer size.  I’m trying to write a checker that will make sure that any buffer access is in bounds by checking that 0 <= offset and offset + chunk_size < buffer_size, where chunk_size is the size of the data being read from / written to the buffer.

Your suggestions have helped a lot, but I’m still stuck getting from the Buffer (struct) SVal to its RecordType.  You said to use SVal::getAsRegion() method to get the MemRegion.  The next step would seem to be using the getValueType() and getAsStructureType() methods, but first I need to convert the MemRegion to a VarRegion or a TypedValueRegion.  I tried each of these (using MemRegion::getAs), but both resulted in the checker crashing.


From: Alexey Sidorin [mailto:alexey.v.sidorin at ya.ru]
Sent: Monday, May 09, 2016 5:16 PM
To: McDowell, Raymond C.; cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>
Subject: Re: [cfe-dev] Static Checker: getting svals for a struct field value

Hello Raymond,

1. You can get the Store with ProgramState::getStore() method().
2. To process an SVal representing a region, you may use SVal::getAsRegion() method. But I'm not sure what you really need here, could you explain more detailedly?
3. Your approach for FieldRegion will work, but it is better to search for a FieldDecl in your RecordDecl first and only then get its FieldRegion. FieldDecl has getName() method allowing doing this, so your code will look like:
for (const auto *F : structRD->fields()) {
  if (F->getName == "fieldName") {
    FieldRegion *FR = MRMgr.getFieldRegion(F, structReg);
    size = State->getSVal(FR);
}
}

where State is of ProgramStateRef type.


09.05.2016 21:55, McDowell, Raymond C. via cfe-dev пишет:
I am new to building Clang static checkers and need some help.  I am implementing a PreCall callback function that checks calls to a certain family of functions (from a local library) that takes a struct as an argument.  I see how to get the SVal and Expr for the argument using CallEvent::getArgSVal() and CallEvent::getArgExpr().  What I’m struggling with is how to go from the SVal for the struct to an SVal for one of its fields.  In particular, how do I get the memory region associated with the struct value?  Once I have that, I think I know how to go from there, e.g.:

RecordType *structTy = structReg->getValueType()->getAsStructureType();
assert(structTy && “Value is not a structure”);
RecordDecl *structRD = structTy ->getDecl()->getDefinition();
assert(structRD && “structure has no definition”);
for (const auto *F : structRD->fields()) {
    FieldRegion *FR = MRMgr.getFieldRegion(F, structReg);
    if (FR->getDec()->getName() == “fieldName”)
        size = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
}

But how do I get the memory region structReg?  And how do I get the Store store?

Thanks!



_______________________________________________

cfe-dev mailing list

cfe-dev at lists.llvm.org<mailto:cfe-dev at lists.llvm.org>

http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20160603/b7ca3445/attachment.html>


More information about the cfe-dev mailing list