[PATCH v3] Bug 14526 - Make malloc() static analysis M_ZERO-aware

Jordan Rose jordan_rose at apple.com
Fri Mar 21 10:37:39 PDT 2014


On Mar 21, 2014, at 10:25, Meyer, Conrad <conrad.meyer at isilon.com> wrote:

> On Fri, Mar 21, 2014 at 1:11 PM, Jordan Rose <jordan_rose at apple.com> wrote:
>> 
>> On Mar 20, 2014, at 6:08 , Meyer, Conrad <conrad.meyer at isilon.com> wrote:
>> 
>>> +  mutable Optional<uint64_t> Val_M_ZERO;
>> 
>> Let's rename this something generic, like KernelZeroFlagVal;
>> 
> 
> Easy to do.
> 
>> 
>>> 
>>>  void initIdentifierInfo(ASTContext &C) const;
>>> 
>>>  /// \brief Determine family of a deallocation expression.
>>>  AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;
>>> @@ -251,10 +255,15 @@ private:
>>>  static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
>>>                                     SVal SizeEx, SVal Init,
>>>                                     ProgramStateRef State,
>>>                                     AllocationFamily Family = AF_Malloc);
>>> 
>>> +  // Check if this malloc() uses M_ZERO or __GFP_ZERO (treat like calloc).
>>> +  llvm::Optional<ProgramStateRef>
>>> +  MallocZero(const CallExpr *CE, CheckerContext &C,
>>> +             const ProgramStateRef &State) const;
>>> +
>> 
>> How about something like "performKernelMalloc"? The special thing here is that it handles the two- and three-argument forms if it knows how. We may want to add support for the other flags some day.
> 
> Sure.
> 
>> 
>> Are there ever going to be systems that have both kmalloc and malloc-with-flags?
> 
> BSD has a Linux kernel compatibility layer for some dual-licensed drivers ("OFED," I think, and possibly others). And I wouldn't be surprised to see the opposite direction either. So while I don't *know* that such a system exists, it wouldn't be super surprising either.
> 
>>> 
>>> +llvm::Optional<ProgramStateRef> MallocChecker::MallocZero(const CallExpr *CE,
>>> +  CheckerContext &C, const ProgramStateRef &State) const {
>>> +  // 3-argument malloc(), as commonly used in {Free,Net,Open}BSD Kernels:
>>> +  //
>>> +  // void *malloc(unsigned long size, struct malloc_type *mtp, int flags);
>>> +  //
>>> +  // One of the possible flags is M_ZERO, which means 'give me back an
>>> +  // allocation which is already zeroed', like calloc.
>>> +
>>> +  // 2-argument kmalloc(), as used in the Linux kernel:
>>> +  //
>>> +  // void *kmalloc(size_t size, gfp_t flags);
>>> +  //
>>> +  // Has the similar flag value __GFP_ZERO.
>>> +
>>> +  // This logic is largely cloned from O_CREAT in UnixAPIChecker, maybe some
>>> +  // code could be shared.
>>> +
>>> +  llvm::Triple::OSType os = C.getASTContext().getTargetInfo().getTriple().getOS();
>>> +  llvm::Optional<ProgramStateRef> RetVal;
>>> +
>>> +  if (!Val_M_ZERO.hasValue()) {
>>> +    if (os == llvm::Triple::FreeBSD)
>>> +      Val_M_ZERO = 0x0100;
>>> +    else if (os == llvm::Triple::NetBSD)
>>> +      Val_M_ZERO = 0x0002;
>>> +    else if (os == llvm::Triple::OpenBSD)
>>> +      Val_M_ZERO = 0x0008;
>>> +    else if (os == llvm::Triple::Linux)
>>> +      // __GFP_ZERO
>>> +      Val_M_ZERO = 0x8000;
>>> +    else
>>> +      // FIXME: We need a more general way of getting the M_ZERO value.
>>> +      // See also: O_CREAT in UnixAPIChecker.cpp.
>>> +
>>> +      // Fall back to normal malloc behavior on platforms where we don't
>>> +      // know M_ZERO.
>>> +      return RetVal;
>> 
>> This can be written "return None;". "None" implicitly converts to an empty Optional.
> 
> Is None a special global or #define in LLVM/Clang? I haven't heard of it in C++ before. But that's easy enough to change.

Check out clang/Basic/LLVM.h, llvm/ADT/None.h, and llvm/ADT/Optional.h. It's special, but just using the rules of C++ to do what we want.

Jordan



More information about the cfe-commits mailing list