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

Meyer, Conrad conrad.meyer at isilon.com
Fri Mar 21 10:25:27 PDT 2014


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.

>
> If you use this everywhere, you don't need to predeclare RetVal.

Sure.

>
> Other than that this looks pretty good!
>
> Jordan

Cool. I will make the suggested changes and re-send.

Thanks,
Conrad




More information about the cfe-commits mailing list